├── font ├── entypo.ttf ├── Roboto-Bold.ttf ├── Roboto-Light.ttf ├── Roboto-Regular.ttf └── NotoEmoji-Regular.ttf ├── docs ├── bibliography.bib ├── examples.md ├── Doxyfile ├── footer.html ├── header.html └── user_concepts.md ├── .clang-format ├── .bettercodehub.yml ├── .gitignore ├── .github └── workflows │ ├── macos-unit.yml │ ├── windows-unit.yml │ ├── llvm-asan.yml │ ├── validate-files.yml │ ├── coverage.yml │ ├── ubuntu-unit.yml │ └── validate-and-deploy-files.yml ├── CONTRIBUTING.md ├── tests ├── CMakeLists.txt ├── DummyDraw.hpp ├── TestUserConcepts.cpp ├── TestFontManager.cpp ├── DummyDraw.cpp ├── TestStyle.cpp ├── TestGeometry.cpp ├── TestLegend.cpp ├── TestCSVDownloader.cpp ├── TestTransformMatrix.cpp ├── TestHistogram.cpp ├── TestColors.cpp ├── TestInteractive.cpp ├── TestBBox.cpp ├── TestAxis.cpp └── TestFigure.cpp ├── examples ├── CMakeLists.txt ├── Rectangle.cpp ├── Line.cpp ├── Points.cpp ├── LineStyle.cpp ├── FacetPoints.cpp ├── Histogram.cpp ├── AnimatedLine.cpp └── AnimatedPoints.cpp ├── LICENSE ├── src ├── frontend │ ├── Histogram.cpp │ ├── Legend.cpp │ ├── Geometry.tcc │ ├── DrawableDraw.hpp │ ├── DrawableDerived.hpp │ ├── Geometry.cpp │ ├── Legend.hpp │ ├── Transform.hpp │ ├── Drawable.cpp │ ├── Legend.tcc │ ├── Line.hpp │ ├── Histogram.hpp │ ├── Points.hpp │ ├── Rectangle.hpp │ ├── Figure.cpp │ ├── Transform.cpp │ ├── Figure.tcc │ ├── Figure.hpp │ └── Histogram.tcc ├── trase.hpp ├── util │ ├── Exception.hpp │ ├── Style.cpp │ ├── Style.hpp │ ├── CSVDownloader.hpp │ ├── ColumnIterator.hpp │ ├── Colors.hpp │ └── CSVDownloader.cpp └── backend │ └── Backend.cpp ├── .codedocs ├── third-party └── nanovg │ └── nanovg_gl_utils.h └── README.md /font/entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trase-cpp/trase/HEAD/font/entypo.ttf -------------------------------------------------------------------------------- /font/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trase-cpp/trase/HEAD/font/Roboto-Bold.ttf -------------------------------------------------------------------------------- /font/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trase-cpp/trase/HEAD/font/Roboto-Light.ttf -------------------------------------------------------------------------------- /font/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trase-cpp/trase/HEAD/font/Roboto-Regular.ttf -------------------------------------------------------------------------------- /font/NotoEmoji-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trase-cpp/trase/HEAD/font/NotoEmoji-Regular.ttf -------------------------------------------------------------------------------- /docs/bibliography.bib: -------------------------------------------------------------------------------- 1 | @book{wilkinson2006grammar, 2 | title={The grammar of graphics}, 3 | author={Wilkinson, Leland}, 4 | year={2006}, 5 | publisher={Springer Science \& Business Media} 6 | } 7 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # This is a very mimimal clang-format config file, based on the LLVM style 3 | # 4 | # For more options see the clang-format documentation, or try using the 5 | # online clang-format generator: 6 | # https://zed0.co.uk/clang-format-configurator/ 7 | # 8 | 9 | BasedOnStyle: LLVM 10 | 11 | ... 12 | -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | This should be a list of examples: 5 | 6 | - @subpage example_line 7 | - @subpage example_animated_line 8 | - @subpage example_line_style 9 | - @subpage example_histogram 10 | - @subpage example_points 11 | - @subpage example_animated_points 12 | - @subpage example_rectangle 13 | 14 | -------------------------------------------------------------------------------- /.bettercodehub.yml: -------------------------------------------------------------------------------- 1 | component_depth: 2 2 | languages: 3 | - name: cpp 4 | production: 5 | exclude: 6 | - /tests/.*\.cpp 7 | - /third-party/.* 8 | - /docs/.* 9 | - /font/.* 10 | - /tests/catch.hpp 11 | test: 12 | include: 13 | - /tests/.*\.cpp 14 | - /examples/.*\.cpp 15 | exclude: 16 | - /third-party/.* 17 | - /docs/.* 18 | - /font/.* 19 | - /tests/catch.hpp 20 | -------------------------------------------------------------------------------- /docs/Doxyfile: -------------------------------------------------------------------------------- 1 | INPUT = README.md src docs docs/examples.md tests/TestUserConcepts.cpp examples 2 | RECURSIVE = YES 3 | USE_MDFILE_AS_MAINPAGE = README.md 4 | LAYOUT_FILE = docs/DoxygenLayout.xml 5 | EXAMPLE_PATH = examples 6 | GENERATE_TREEVIEW = YES 7 | CITE_BIB_FILES = docs/bibliography.bib 8 | HTML_EXTRA_STYLESHEET = docs/customdoxygen.css 9 | HTML_FOOTER = docs/footer.html 10 | HTML_HEADER = docs/header.html 11 | IMAGE_PATH = docs/figs 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Visual studio specific files 35 | .vs 36 | CMakeSettings.json 37 | 38 | # Clion specific files 39 | .idea 40 | cmake-build* 41 | 42 | # Build directories 43 | Debug 44 | Release 45 | 46 | # Python virtual environments 47 | venv 48 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/macos-unit.yml: -------------------------------------------------------------------------------- 1 | name: macOS unit 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: macOS unit 15 | runs-on: macos-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: make build directory 21 | run: mkdir build_dir 22 | 23 | - name: cmake configure 24 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE 25 | working-directory: build_dir 26 | 27 | - name: cmake build 28 | run: cmake --build . --parallel 2 29 | working-directory: build_dir 30 | 31 | - name: cmake test 32 | run: ctest -j2 --output-on-failure 33 | working-directory: build_dir 34 | -------------------------------------------------------------------------------- /.github/workflows/windows-unit.yml: -------------------------------------------------------------------------------- 1 | name: Windows unit 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: Windows unit 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: make build directory 21 | run: mkdir build_dir 22 | 23 | - name: cmake configure 24 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE 25 | working-directory: build_dir 26 | 27 | - name: cmake build 28 | run: cmake --build . --parallel 2 29 | working-directory: build_dir 30 | 31 | - name: cmake test 32 | run: ctest -j2 --output-on-failure 33 | working-directory: build_dir 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Trase 2 | 3 | We welcome new Pull Requests from the community in order to improve and grow 4 | Trase. If you have a bug-fix/feature/refactor/other that you wish to contribute, 5 | please discuss it first via email, issue or any other method with the Trase 6 | developers, listed below. 7 | 8 | ## Pull Requests Process 9 | 10 | 1. Fork the Trase repo and add your change 11 | 2. Add necessary unit tests to maintain coverage in `tests/`. Ensure all tests 12 | pass. 13 | 3. Create a Pull Request via GitHub. This can be merged once all the continuous 14 | integration testing has succeeded, and it has been approved by at least one 15 | other developer. 16 | 17 | ## Developers 18 | 19 | Links to profile pages below, which includes email contact info 20 | 21 | - [Martin Robinson](https://github.com/martinjrobins) 22 | - [Fergus Cooper](https://github.com/fcooper8472) 23 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (trase_BUILD_OPENGL) 3 | add_executable (interactive_test TestInteractive.cpp) 4 | target_link_libraries (interactive_test PRIVATE trase) 5 | endif () 6 | 7 | add_executable ( 8 | trase_test 9 | DummyDraw.hpp 10 | DummyDraw.cpp 11 | TestAxis.cpp 12 | TestData.cpp 13 | TestBackendSVG.cpp 14 | TestBBox.cpp 15 | TestColors.cpp 16 | TestFigure.cpp 17 | TestFontManager.cpp 18 | TestGeometry.cpp 19 | TestHistogram.cpp 20 | TestPoints.cpp 21 | TestRectangle.cpp 22 | TestUserConcepts.cpp 23 | TestStyle.cpp 24 | TestTransformMatrix.cpp 25 | TestVector.cpp 26 | TestLegend.cpp 27 | ) 28 | if (CURL_FOUND) 29 | target_sources(trase_test PRIVATE TestCSVDownloader.cpp) 30 | endif (CURL_FOUND) 31 | 32 | target_include_directories (trase_test PRIVATE tests) 33 | target_link_libraries (trase_test PRIVATE trase) 34 | add_test (the_trase_test trase_test) 35 | 36 | 37 | -------------------------------------------------------------------------------- /.github/workflows/llvm-asan.yml: -------------------------------------------------------------------------------- 1 | name: llvm asan 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: llvm asan 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: install dependencies 21 | run: sudo apt install libcurl4-openssl-dev 22 | 23 | - name: install compiler 24 | run: sudo apt install clang-9 25 | 26 | - name: make build directory 27 | run: mkdir build_dir 28 | 29 | - name: cmake configure 30 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE -Dtrase_MEMCHECK:BOOL=TRUE 31 | working-directory: build_dir 32 | env: 33 | CC: clang-9 34 | CXX: clang++-9 35 | 36 | - name: cmake build 37 | run: cmake --build . --parallel 2 38 | working-directory: build_dir 39 | 40 | - name: cmake test 41 | run: ctest -j2 --output-on-failure 42 | working-directory: build_dir 43 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # list of examples 2 | set (examples 3 | Line.cpp 4 | AnimatedLine.cpp 5 | Histogram.cpp 6 | AnimatedPoints.cpp 7 | LineStyle.cpp 8 | Rectangle.cpp 9 | ) 10 | 11 | 12 | # list of examples that need curl 13 | find_package(CURL) 14 | if (CURL_FOUND) 15 | list(APPEND examples 16 | Points.cpp 17 | FacetPoints.cpp 18 | ) 19 | endif(CURL_FOUND) 20 | 21 | foreach (file IN LISTS examples) 22 | get_filename_component (name ${file} NAME_WE) 23 | string(TOLOWER ${name} name) 24 | 25 | add_executable (${name} ${file}) 26 | target_link_libraries (${name} PRIVATE trase) 27 | target_compile_definitions (${name} PRIVATE TRASE_EXAMPLES_SVG_BACKEND) 28 | if (CURL_FOUND) 29 | target_link_libraries (${name} PRIVATE ${CURL_LIBRARIES}) 30 | target_include_directories(${name} PRIVATE ${CURL_INCLUDE_DIRS}) 31 | endif (CURL_FOUND) 32 | add_test (example_${name} ${name}) 33 | 34 | if (trase_BUILD_OPENGL) 35 | add_executable (${name}_gl ${file}) 36 | target_link_libraries (${name}_gl PRIVATE trase) 37 | target_compile_definitions (${name}_gl PRIVATE TRASE_EXAMPLES_GL_BACKEND) 38 | endif () 39 | endforeach(file) 40 | 41 | -------------------------------------------------------------------------------- /.github/workflows/validate-files.yml: -------------------------------------------------------------------------------- 1 | name: validate svg files 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - '**' 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: validate svg files 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: install dependencies 21 | run: sudo apt install libcurl4-openssl-dev 22 | 23 | - name: make build directory 24 | run: mkdir build_dir 25 | 26 | - name: cmake configure 27 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE 28 | working-directory: build_dir 29 | 30 | - name: cmake build 31 | run: cmake --build . --parallel 2 32 | working-directory: build_dir 33 | 34 | - name: cmake test 35 | run: ctest -j2 --output-on-failure 36 | working-directory: build_dir 37 | 38 | - name: validate svg 39 | run: | 40 | pip3 install --upgrade pip setuptools wheel 41 | pip3 install html5validator 42 | /home/runner/.local/bin/html5validator --root . --match "*.svg" --also-check-svg --ignore "exception_trase_invalid_svg" 43 | working-directory: build_dir 44 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: coverage 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: coverage 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: install dependencies 21 | run: sudo apt install lcov libcurl4-openssl-dev 22 | 23 | - name: make build directory 24 | run: mkdir build_dir 25 | 26 | - name: cmake configure 27 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE -Dtrase_ENABLE_COVERAGE:BOOL=TRUE 28 | working-directory: build_dir 29 | 30 | - name: cmake build 31 | run: cmake --build . --parallel 2 32 | working-directory: build_dir 33 | 34 | - name: cmake test 35 | run: ctest -j2 --output-on-failure 36 | working-directory: build_dir 37 | 38 | - name: upload coverage results 39 | run: | 40 | lcov --directory . --capture --output-file coverage.info 41 | lcov --remove coverage.info '/usr/*' '*/tests/*' --output-file coverage.info 42 | lcov --list coverage.info 43 | bash <(curl https://codecov.io/bash) -f coverage.info 44 | env: 45 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 46 | working-directory: build_dir 47 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu-unit.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu unit 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: Ubuntu unit ${{matrix.CC}} 15 | runs-on: ubuntu-latest 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | include: 20 | - CC: gcc-7 21 | CXX: g++-7 22 | compiler: gcc-7 g++-7 23 | - CC: gcc-8 24 | CXX: g++-8 25 | compiler: gcc-8 g++-8 26 | - CC: gcc-9 27 | CXX: g++-9 28 | compiler: gcc-9 g++-9 29 | - CC: clang-6.0 30 | CXX: clang++-6.0 31 | compiler: clang-6.0 32 | - CC: clang-8 33 | CXX: clang++-8 34 | compiler: clang-8 35 | - CC: clang-9 36 | CXX: clang++-9 37 | compiler: clang-9 38 | 39 | steps: 40 | - uses: actions/checkout@v2 41 | 42 | - name: install dependencies 43 | run: sudo apt install libcurl4-openssl-dev 44 | 45 | - name: install compiler 46 | run: sudo apt install ${{matrix.compiler}} 47 | 48 | - name: make build directory 49 | run: mkdir build_dir 50 | 51 | - name: cmake configure 52 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE 53 | working-directory: build_dir 54 | env: 55 | CC: ${{matrix.CC}} 56 | CXX: ${{matrix.CXX}} 57 | 58 | - name: cmake build 59 | run: cmake --build . --parallel 2 60 | working-directory: build_dir 61 | 62 | - name: cmake test 63 | run: ctest -j2 --output-on-failure 64 | working-directory: build_dir 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, University of Oxford. 4 | All rights reserved. 5 | 6 | University of Oxford means the Chancellor, Masters and Scholars of the 7 | University of Oxford, having an administrative office at Wellington 8 | Square, Oxford OX1 2JD, UK. 9 | 10 | This file is part of the Oxford RSE C++ Template project. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are met: 14 | * Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | * Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | * Neither the name of the copyright holder nor the names of its 20 | contributors may be used to endorse or promote products derived from 21 | this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 29 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | -------------------------------------------------------------------------------- /src/frontend/Histogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "frontend/Histogram.hpp" 35 | 36 | namespace trase {} // namespace trase 37 | -------------------------------------------------------------------------------- /.github/workflows/validate-and-deploy-files.yml: -------------------------------------------------------------------------------- 1 | name: validate and deploy files 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches-ignore: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: validate and deploy files 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: make build directory 21 | run: mkdir build_dir 22 | 23 | - name: cmake configure 24 | run: cmake .. -DCMAKE_BUILD_TYPE=Debug -Dtrase_BUILD_OPENGL:BOOL=FALSE 25 | working-directory: build_dir 26 | 27 | - name: cmake build 28 | run: cmake --build . --parallel 2 29 | working-directory: build_dir 30 | 31 | - name: cmake test 32 | run: ctest -j2 --output-on-failure 33 | working-directory: build_dir 34 | 35 | - name: validate svg 36 | run: | 37 | pip3 install --upgrade pip setuptools wheel 38 | pip3 install html5validator 39 | /home/runner/.local/bin/html5validator --root . --match "*.svg" --also-check-svg --ignore "exception_trase_invalid_svg" 40 | working-directory: build_dir 41 | 42 | - name: deploy files 43 | run: | 44 | git clone https://github.com/trase-cpp/generated_files.git 45 | rm generated_files/examples/*.svg 46 | rm generated_files/tests/*.svg 47 | cp examples/*.svg generated_files/examples/ 48 | cp tests/*.svg generated_files/tests/ 49 | cd generated_files 50 | git add examples/*.svg tests/*.svg 51 | git -c user.name='github-action' -c user.email='github-action' commit -a -m "updated generated files" 52 | git push -q https://martinjrobins:$DEPLOY_ACCESS_TOKEN@github.com/trase-cpp/generated_files master &>/dev/null 53 | working-directory: build_dir 54 | env: 55 | DEPLOY_ACCESS_TOKEN: ${{ secrets.DEPLOY_ACCESS_TOKEN }} 56 | -------------------------------------------------------------------------------- /src/frontend/Legend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "Legend.hpp" 35 | 36 | namespace trase { 37 | 38 | Legend::Legend(Drawable *parent, const bfloat2_t &area) 39 | : Drawable(parent, area) {} 40 | 41 | } // namespace trase 42 | -------------------------------------------------------------------------------- /src/frontend/Geometry.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | #include "frontend/Geometry.hpp" 37 | 38 | namespace trase { 39 | 40 | template 41 | void Geometry::draw(AnimatedBackend &backend) {} 42 | 43 | template 44 | void Geometry::draw(Backend &backend, const float time) {} 45 | 46 | } // namespace trase 47 | -------------------------------------------------------------------------------- /src/trase.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file trase.hpp 35 | 36 | #ifndef TRASE_H_ 37 | #define TRASE_H_ 38 | 39 | #include "backend/BackendSVG.hpp" 40 | #ifdef TRASE_BACKEND_GL 41 | #include "backend/BackendGL.hpp" 42 | #endif 43 | 44 | #include "frontend/Figure.hpp" 45 | #ifdef TRASE_HAVE_CURL 46 | #include "util/CSVDownloader.hpp" 47 | #endif 48 | 49 | #endif // TRASE_H_ 50 | -------------------------------------------------------------------------------- /src/util/Exception.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Exception.hpp 35 | 36 | #ifndef _EXCEPTION_H_ 37 | #define _EXCEPTION_H_ 38 | 39 | #include 40 | 41 | namespace trase { 42 | 43 | class Exception : public std::runtime_error { 44 | public: 45 | explicit Exception(const std::string &arg) : std::runtime_error(arg){}; 46 | }; 47 | 48 | } // namespace trase 49 | 50 | #endif // _EXCEPTION_H_ 51 | -------------------------------------------------------------------------------- /tests/DummyDraw.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Style.hpp 35 | 36 | #ifndef DUMMY_DRAW_H_ 37 | #define DUMMY_DRAW_H_ 38 | 39 | #include "trase.hpp" 40 | #include 41 | #include 42 | 43 | namespace trase { 44 | struct DummyDraw { 45 | static int m_num_dummy_draw; 46 | static void draw(const std::string &base_name, std::shared_ptr
&fig); 47 | }; 48 | } // namespace trase 49 | 50 | #endif // DUMMY_DRAW_H_ 51 | -------------------------------------------------------------------------------- /src/frontend/DrawableDraw.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file DrawableDraw.hpp 35 | /// 36 | /// How to draw Drawable 37 | /// 38 | /// These are included only when compiling the backends 39 | 40 | #include "frontend/Drawable.hpp" 41 | 42 | namespace trase { 43 | 44 | template 45 | void Drawable::draw(Backend &backend, const float time) {} 46 | 47 | template void Drawable::draw(AnimatedBackend &out) {} 48 | 49 | } // namespace trase 50 | -------------------------------------------------------------------------------- /docs/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | $projectname: $title 10 | $title 11 | 12 | 13 | 14 | $treeview 15 | $search 16 | $mathjax 17 | 18 | $extrastylesheet 19 | 20 | 21 |
22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
33 |
$projectname 34 |  $projectnumber 35 |
36 |
$projectbrief
37 |
42 |
$projectbrief
43 |
$searchbox
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /src/frontend/DrawableDerived.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Geometry.hpp 35 | /// available geometry types are Points, Line. Any new sub-classes need to be 36 | /// added here 37 | 38 | #ifndef DRAWABLE_DERIVED_H_ 39 | #define DRAWABLE_DERIVED_H_ 40 | 41 | #include "frontend/Axis.hpp" 42 | #include "frontend/Figure.hpp" 43 | #include "frontend/Histogram.hpp" 44 | #include "frontend/Line.hpp" 45 | #include "frontend/Plot1D.hpp" 46 | #include "frontend/Points.hpp" 47 | 48 | #endif // DRAWABLE_DERIVED_H_ 49 | -------------------------------------------------------------------------------- /tests/TestUserConcepts.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include "backend/BackendSVG.hpp" 37 | #include "trase.hpp" 38 | #include 39 | 40 | TEST_CASE("snippits for user_concepts.md", "[documentation]") { 41 | /// [user_concepts_data_set] 42 | using namespace trase; 43 | std::vector x = {1, 2, 3, 4}; 44 | std::vector y = {2, 4, 6, 8}; 45 | 46 | auto data = create_data().x(x).y(y); 47 | /// [user_concepts_data_set] 48 | /// [user_concepts_geometry] 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | auto plt = ax->line(data); 52 | /// [user_concepts_geometry] 53 | } 54 | -------------------------------------------------------------------------------- /tests/TestFontManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include 37 | #include 38 | 39 | #include "backend/Backend.hpp" 40 | 41 | TEST_CASE("find fonts", "[font manager]") { 42 | 43 | // Default construction 44 | trase::FontManager fm; 45 | 46 | auto font = fm.find_font("Roboto-Regular", ""); 47 | CHECK(!font.empty()); 48 | CHECK(font.find("Roboto-Regular") != std::string::npos); 49 | CHECK(font.find(".ttf") != std::string::npos); 50 | 51 | font = fm.find_font("SomeCrazyFontThatCantExist", ""); 52 | CHECK(font.empty()); 53 | 54 | fm.clear_font_dirs(); 55 | fm.add_font_dir("nonexistant_dir"); 56 | font = fm.find_font("Roboto-Regular", ""); 57 | CHECK(font.empty()); 58 | } 59 | -------------------------------------------------------------------------------- /tests/DummyDraw.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "DummyDraw.hpp" 35 | #include 36 | 37 | namespace trase { 38 | int DummyDraw::m_num_dummy_draw = 0; 39 | void DummyDraw::draw(const std::string &base_name, 40 | std::shared_ptr
&fig) { 41 | std::ofstream out; 42 | out.open("test_" + base_name + std::to_string(++m_num_dummy_draw) + ".svg"); 43 | BackendSVG backend(out); 44 | fig->draw(backend); 45 | out.close(); 46 | out.open("test_" + base_name + std::to_string(++m_num_dummy_draw) + ".svg"); 47 | BackendSVG backend_single(out); 48 | fig->draw(backend_single, 0); 49 | out.close(); 50 | out.open("test_" + base_name + std::to_string(++m_num_dummy_draw) + ".svg"); 51 | BackendSVG backend_single2(out); 52 | fig->draw(backend_single2, fig->time_span()/2.f); 53 | out.close(); 54 | } 55 | 56 | } // namespace trase 57 | -------------------------------------------------------------------------------- /src/util/Style.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "util/Style.hpp" 35 | 36 | namespace trase { 37 | 38 | float Style::line_width() const noexcept { return m_line_width; } 39 | 40 | float Style::font_size() const noexcept { return m_font_size; } 41 | 42 | RGBA Style::color() const noexcept { return m_color; } 43 | 44 | std::string Style::font() const noexcept { return m_font; } 45 | 46 | Style &Style::line_width(const float lineWidth) noexcept { 47 | m_line_width = lineWidth; 48 | return *this; 49 | } 50 | 51 | Style &Style::font_size(const float fontSize) noexcept { 52 | m_font_size = fontSize; 53 | return *this; 54 | } 55 | 56 | Style &Style::color(const RGBA color) noexcept { 57 | m_color = color; 58 | return *this; 59 | } 60 | 61 | Style &Style::font(const std::string font) noexcept { 62 | m_font = font; 63 | return *this; 64 | } 65 | 66 | } // namespace trase 67 | -------------------------------------------------------------------------------- /src/frontend/Geometry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "frontend/Axis.hpp" 35 | #include "frontend/Geometry.hpp" 36 | 37 | #include 38 | 39 | #include "util/Vector.hpp" 40 | 41 | namespace trase { 42 | 43 | Geometry::Geometry(Axis *parent) 44 | : Drawable(parent, bfloat2_t(vfloat2_t(0, 0), vfloat2_t(1, 1))), 45 | m_colormap(&Colormaps::viridis), m_axis(parent) {} 46 | 47 | void Geometry::add_frame(const DataWithAesthetic &data, float time) { 48 | // add new data frame 49 | m_data.push_back(m_transform(data)); 50 | 51 | // add new frame time 52 | if (time > 0) { 53 | add_frame_time(time); 54 | } 55 | 56 | // update limits with new frame 57 | m_limits += m_data.back().limits(); 58 | 59 | // communicate limits to parent axis 60 | const float buffer = 1.05f; 61 | dynamic_cast(m_parent)->limits() += 62 | m_limits * Limits::vector_t::Constant(buffer); 63 | } 64 | 65 | } // namespace trase 66 | -------------------------------------------------------------------------------- /src/frontend/Legend.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Legend.hpp 35 | 36 | #ifndef LEGEND_H_ 37 | #define LEGEND_H_ 38 | 39 | #include "frontend/Axis.hpp" 40 | #include "frontend/Drawable.hpp" 41 | #include 42 | 43 | namespace trase { 44 | 45 | class Legend : public Drawable { 46 | std::vector> m_entries; 47 | 48 | public: 49 | Legend(Drawable *parent, const bfloat2_t &area); 50 | 51 | virtual ~Legend() = default; 52 | 53 | TRASE_DISPATCH_BACKENDS 54 | 55 | void add_entry(const std::shared_ptr &entry) { 56 | m_entries.push_back(entry); 57 | } 58 | 59 | template void draw(AnimatedBackend &backend); 60 | template void draw(Backend &backend, float time); 61 | 62 | private: 63 | template 64 | void draw_common(Backend &backend, const DispatchF &dispatch); 65 | }; 66 | 67 | } // namespace trase 68 | 69 | #include "frontend/Legend.tcc" 70 | 71 | #endif // PLOT1D_H_ 72 | -------------------------------------------------------------------------------- /src/util/Style.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Style.hpp 35 | 36 | #ifndef STYLE_H_ 37 | #define STYLE_H_ 38 | 39 | #include "util/Colors.hpp" 40 | 41 | namespace trase { 42 | 43 | class Style { 44 | 45 | /// the line width 46 | float m_line_width{3.f}; 47 | 48 | /// the font size 49 | float m_font_size{18.f}; 50 | 51 | /// the color 52 | RGBA m_color{RGBA::black}; 53 | 54 | /// the font 55 | std::string m_font{"Roboto"}; 56 | 57 | public: 58 | /// constructor 59 | Style() = default; 60 | 61 | /// get the current line width 62 | float line_width() const noexcept; 63 | 64 | /// get the current font size 65 | float font_size() const noexcept; 66 | 67 | /// get the current colour 68 | RGBA color() const noexcept; 69 | 70 | /// get the current font 71 | std::string font() const noexcept; 72 | 73 | /// set the new line width 74 | Style &line_width(float lineWidth) noexcept; 75 | 76 | /// set the new font size 77 | Style &font_size(float fontSize) noexcept; 78 | 79 | /// set the new color 80 | Style &color(RGBA color) noexcept; 81 | 82 | /// set the new font 83 | Style &font(std::string font) noexcept; 84 | }; 85 | 86 | } // namespace trase 87 | 88 | #endif // STYLE_H_ 89 | -------------------------------------------------------------------------------- /tests/TestStyle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include "util/Colors.hpp" 37 | #include "util/Style.hpp" 38 | 39 | #include "trase.hpp" 40 | 41 | TEST_CASE("style construction and defaults", "[style]") { 42 | 43 | trase::Style s{}; 44 | 45 | CHECK(s.line_width() == 3.f); 46 | CHECK(s.font_size() == 18.f); 47 | CHECK(s.font() == "Roboto"); 48 | CHECK(s.color() == trase::RGBA::black); 49 | } 50 | 51 | TEST_CASE("style on drawable", "[style]") { 52 | 53 | auto fig = trase::figure({800, 600}); 54 | auto ax = fig->axis(); 55 | 56 | const trase::Style &s = ax->style(); 57 | 58 | // Create a new style 59 | trase::Style my_style; 60 | CHECK(s.line_width() == my_style.line_width()); 61 | 62 | // Change line width in my_style and set it as new style on the axis 63 | my_style.line_width(1.23f); 64 | ax->style() = my_style; 65 | CHECK(s.line_width() == 1.23f); 66 | } 67 | 68 | TEST_CASE("style setting and getting", "[style]") { 69 | 70 | trase::Style my_style; 71 | 72 | trase::RGBA my_col{1, 2, 3, 4}; 73 | 74 | my_style.line_width(2.3f).font_size(3.4f).color(my_col).font("a string"); 75 | 76 | CHECK(my_style.line_width() == 2.3f); 77 | CHECK(my_style.font_size() == 3.4f); 78 | CHECK(my_style.color() == my_col); 79 | CHECK(my_style.font() == "a string"); 80 | } 81 | -------------------------------------------------------------------------------- /docs/user_concepts.md: -------------------------------------------------------------------------------- 1 | User Concepts 2 | ============= 3 | 4 | Trase roughly follows the same concepts as described in the Grammer of Graphics 5 | \cite wilkinson2006grammar. In general, three different items must be defined to 6 | create each plot, these are: 7 | 8 | 1. **A Dataset with Aesthetics** (\ref trase::DataWithAesthetic) - A dataset is 9 | a \f$n \times m\f$ matrix of data, where \f$n\f$ is the number of data 10 | points (i.e. rows) and \f$m\f$ is the number of columns. Each column of this 11 | matrix is labelled with a given \ref trase::Aesthetic. Currently there are 4 12 | different aesthetics in Trase: \ref trase::Aesthetic::x, 13 | \ref trase::Aesthetic::y, \ref trase::Aesthetic::size, and 14 | \ref trase::Aesthetic::color. A user will normally create a dataset using 15 | the \ref trase::create\_data() function, by passing in columns of data using 16 | a `std::vector` labelled with a given Aesthetic. For example: 17 | 18 | \snippet tests/TestUserConcepts.cpp user\_concepts\_data\_set 19 | 20 | \note When creating a \ref trase::DataWithAesthetic object using 21 | \ref trase::create\_data, the Aesthetic labels are set using member 22 | functions of the \ref trase::DataWithAesthetic class. These return 23 | references to the \ref trase::DataWithAesthetic object and can thus be 24 | chained together. 25 | 26 | 2. **A Geometry** (\ref trase::Plot1D) - A Geometry defines how the data is 27 | displayed in the plot. It takes columns of data corresponding to specific 28 | Aesthetics and draws them in a certain way. A simple example of this is a 29 | line plot, which draws linear line segments between 2D points given by the x 30 | and y Aesthetics. A geometry is created by calling a specific member 31 | function of the figure axis, for example, the following code creates a 32 | figures and then creates a line geometry on that figure's (default) axis 33 | object 34 | 35 | \snippet tests/TestUserConcepts.cpp user\_concepts\_geometry 36 | 37 | Below is a table of currently implemented geometries, along with their default 38 | transforms and required Aesthetics. 39 | 40 | Geometry | Default Transform | Required Aesthetics | Creation function | 41 | -----------------------| ----------------------| ---------------------|-------------------| 42 | \ref trase::Line | \ref trase::Identity | x, y | trase::Axis::line | 43 | \ref trase::Points | \ref trase::Identity | x, y, color, size | trase::Axis::points | 44 | \ref trase::Histogram | \ref trase::BinX | x | trase::Axis::histogram | 45 | 46 | 47 | 3. **A Transform** (\ref trase::Transform)- A transform maps an input dataset 48 | to an output dataset. For example, the line geometry has the \ref trase::Identity transform as its 49 | default, which simply passes the input unchanged to the output. Each geometry has a default transform, which it 50 | applies to the input dataset prior to displaying the output dataset. 51 | 52 | \note if you wish to change the default transform for a given geometry, just pass in the new transform to the creation function 53 | -------------------------------------------------------------------------------- /examples/Rectangle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_rectangle Rectangle Geometry 35 | /// This is an example for the Rectangle geometry 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_rectangle.svg "Output" 38 | /// \snippet examples/Rectangle.cpp example rectangle 39 | 40 | /// [example rectangle] 41 | #include "trase.hpp" 42 | #include 43 | #include 44 | 45 | using namespace trase; 46 | 47 | int main() { 48 | 49 | std::vector xmin = {1, 3, 1, 5, 4}; 50 | std::vector ymin = {1, 1, 4, 1, 3}; 51 | std::vector xmax = {2, 4, 3, 6, 6}; 52 | std::vector ymax = {2, 2, 5, 3, 5}; 53 | std::vector fill = {0, 0, 0, 1, 1}; 54 | 55 | auto fig = figure(); 56 | auto ax = fig->axis(); 57 | auto data = 58 | create_data().xmin(xmin).ymin(ymin).xmax(xmax).ymax(ymax).fill(fill); 59 | 60 | auto rect = ax->rectangle(data); 61 | 62 | ax->xlabel("x"); 63 | ax->ylabel("y"); 64 | 65 | // output to chosen backend 66 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 67 | std::ofstream out; 68 | out.open("example_rectangle.svg"); 69 | BackendSVG backend(out); 70 | fig->draw(backend); 71 | out.close(); 72 | #endif 73 | #ifdef TRASE_EXAMPLES_GL_BACKEND 74 | BackendGL backend; 75 | fig->show(backend); 76 | #endif 77 | } 78 | /// [example rectangle] 79 | -------------------------------------------------------------------------------- /examples/Line.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_line Line Geometry 35 | /// This is an example for the line geometry 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_line.svg "Output" 38 | /// \snippet examples/Line.cpp example line 39 | 40 | /// [example line] 41 | #include "trase.hpp" 42 | #include 43 | 44 | using namespace trase; 45 | 46 | int main() { 47 | 48 | // create figure and axis 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | 52 | // create x and y vectors and set y = sin(x) 53 | const int n = 100; 54 | std::vector x(n); 55 | std::vector y(n); 56 | for (int i = 0; i < n; ++i) { 57 | x[i] = 6.28f * static_cast(i) / n; 58 | y[i] = std::sin(x[i]); 59 | } 60 | 61 | // create a trase dataset and then plot it using a line geometry 62 | auto data = create_data().x(x).y(y); 63 | auto plt = ax->line(data); 64 | 65 | // label axis 66 | ax->xlabel("x"); 67 | ax->ylabel("y"); 68 | 69 | // output to chosen backend 70 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 71 | std::ofstream out; 72 | out.open("example_line.svg"); 73 | BackendSVG backend(out); 74 | fig->draw(backend); 75 | out.close(); 76 | #endif 77 | #ifdef TRASE_EXAMPLES_GL_BACKEND 78 | BackendGL backend; 79 | fig->show(backend); 80 | #endif 81 | } 82 | /// [example line] 83 | -------------------------------------------------------------------------------- /tests/TestGeometry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | // This tells Catch to provide a main() - only do this in one cpp file 35 | #include "catch.hpp" 36 | 37 | #include 38 | #include 39 | 40 | #include "trase.hpp" 41 | 42 | using namespace trase; 43 | 44 | TEST_CASE("line geometry can be created", "[geometry]") { 45 | auto fig = figure(); 46 | auto ax = fig->axis(); 47 | auto pl1 = ax->line(create_data() 48 | .x(std::vector({0.0f, 0.1f, 0.5f})) 49 | .y(std::vector({0.0f, 0.1f, 0.5f}))); 50 | auto pl2 = ax->line(create_data() 51 | .x(std::vector({0, 1, 2})) 52 | .y(std::vector({0.0f, 0.1f, 0.5f}))); 53 | auto pl3 = ax->line(create_data() 54 | .x(std::vector({0, 1, 2})) 55 | .y(std::vector({0, 2, 4}))); 56 | 57 | // auto pl4 = ax->plot({0, 1, 2}, {0, 2, 4}); 58 | // 59 | REQUIRE_THROWS_WITH( 60 | ax->line(create_data() 61 | .x(std::vector({0.0f, 0.1f})) 62 | .y(std::vector({0.0f, 0.1f, 0.5f}))), 63 | Catch::Contains("columns in dataset must have identical number of rows")); 64 | 65 | std::vector x = {0.0f, 0.1f, 0.5f}; 66 | std::vector y = {0.0f, 0.1f, 0.5f}; 67 | auto data = create_data().x(x).y(y); 68 | auto pl5 = ax->line(data); 69 | } 70 | -------------------------------------------------------------------------------- /examples/Points.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_points Points Geometry 35 | /// This is an example for the points geometry which uses the classic 36 | /// Iris data set 37 | /// 38 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_points.svg "Output" 39 | /// \snippet examples/Points.cpp example points 40 | 41 | /// [example points] 42 | #include "trase.hpp" 43 | #include 44 | #include 45 | 46 | using namespace trase; 47 | 48 | int main() { 49 | CSVDownloader dl; 50 | auto csv = dl.download( 51 | "http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", 52 | {"sepal_length", "sepal_width", "petal_length", "petal_width", "class"}); 53 | auto fig = figure(); 54 | auto ax = fig->axis(); 55 | auto data = create_data() 56 | .x(csv["sepal_length"]) 57 | .y(csv["sepal_width"]) 58 | .color(csv["petal_width"]); 59 | 60 | auto points = ax->points(data); 61 | 62 | ax->xlabel("sepal length"); 63 | ax->ylabel("sepal width"); 64 | 65 | // output to chosen backend 66 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 67 | std::ofstream out; 68 | out.open("example_points.svg"); 69 | BackendSVG backend(out); 70 | fig->draw(backend); 71 | out.close(); 72 | #endif 73 | #ifdef TRASE_EXAMPLES_GL_BACKEND 74 | BackendGL backend; 75 | fig->show(backend); 76 | #endif 77 | } 78 | /// [example points] 79 | -------------------------------------------------------------------------------- /src/util/CSVDownloader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file CSVDownloader.hpp 35 | 36 | #ifndef _CSVDownloader_H_ 37 | #define _CSVDownloader_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | namespace trase { 44 | 45 | class CSVDownloader { 46 | public: 47 | /// columns of csv file returned as a map from string label to a column of 48 | /// data (vector of strings) 49 | using data_t = std::map>; 50 | 51 | /// constructs a csv downloader with default delimiter of ',' 52 | CSVDownloader(); 53 | 54 | ~CSVDownloader(); 55 | 56 | /// download a csv file at the url given by @p url 57 | /// 58 | /// @param url url to download csv file from 59 | /// @param labels if empty, the first line of the csv file is assumed to 60 | /// contain the column labels If not empty, this vector contains the column 61 | /// labels 62 | data_t download(const std::string &url, 63 | const std::vector &labels = {}); 64 | 65 | /// set the delimiter for the csv file format 66 | void set_delim(const char arg) { m_delim = arg; } 67 | 68 | private: 69 | /// parse a csv file given as a `std::stringstream` 70 | CSVDownloader::data_t parse_csv(std::stringstream &out, 71 | const std::vector &labels); 72 | 73 | /// pointer to libcurl data 74 | void *m_curl; 75 | 76 | /// delimiter for the csv file format 77 | char m_delim; 78 | }; 79 | 80 | } // namespace trase 81 | 82 | #endif // _CSVDownloader_H_ 83 | -------------------------------------------------------------------------------- /src/frontend/Transform.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Transform.hpp 35 | 36 | #ifndef TRANSFORM_H_ 37 | #define TRANSFORM_H_ 38 | 39 | #include 40 | 41 | #include "frontend/Data.hpp" 42 | #include "util/BBox.hpp" 43 | 44 | namespace trase { 45 | 46 | /// Identity transform, just pass through... 47 | struct Identity { 48 | DataWithAesthetic operator()(const DataWithAesthetic &data) const { 49 | return data; 50 | } 51 | }; 52 | 53 | /// bin x coordinates 54 | /// 55 | /// Requires x aesthetic. 56 | class BinX { 57 | int m_number_of_bins{-1}; 58 | bbox m_span; 59 | 60 | public: 61 | BinX() = default; 62 | explicit BinX(int number_of_bins); 63 | explicit BinX(int number_of_bins, float min, float max); 64 | DataWithAesthetic operator()(const DataWithAesthetic &data); 65 | }; 66 | 67 | /// holds a `std::function` that maps between two DataWithAesthetic classes 68 | class Transform { 69 | std::function m_transform; 70 | 71 | public: 72 | /// construct an identity transform 73 | Transform() : m_transform(Identity()) {} 74 | 75 | /// construct a Transform wrapping the given transform function T. The 76 | /// function T can be any function or function object that is compatible with 77 | /// `std::function` 78 | template 79 | explicit Transform(const T &transform) : m_transform(transform) {} 80 | 81 | /// perform mapping on `data`, return result 82 | DataWithAesthetic operator()(const DataWithAesthetic &data) { 83 | return m_transform(data); 84 | } 85 | }; 86 | 87 | } // namespace trase 88 | 89 | #endif // TRANSFORM_H_ 90 | -------------------------------------------------------------------------------- /examples/LineStyle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_line_style Line Style 35 | /// This is an example of using the Style class for a Line 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_line_style.svg "Output" 38 | /// \snippet examples/LineStyle.cpp example line style 39 | 40 | /// [example line style] 41 | #include "trase.hpp" 42 | #include 43 | 44 | using namespace trase; 45 | 46 | int main() { 47 | 48 | // create figure and axis 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | 52 | // create x and y vectors 53 | const int n = 100; 54 | std::vector x(n); 55 | std::vector y(n); 56 | const float k = 1.f; 57 | auto logistic = [k](const float x) { return 1.f / (1.f + std::exp(-k * x)); }; 58 | for (int i = 0; i < n; ++i) { 59 | x[i] = -6.f + 12.f * static_cast(i) / n; 60 | y[i] = logistic(x[i]); 61 | } 62 | 63 | // create a trase dataset and then plot it using a line geometry 64 | auto data = create_data().x(x).y(y); 65 | auto plt = ax->line(data); 66 | 67 | // set line color = red and line width = 10 68 | plt->style().color(RGBA(255, 0, 0)).line_width(10); 69 | 70 | // label axis 71 | ax->xlabel("x"); 72 | ax->ylabel("y"); 73 | 74 | // output to chosen backend 75 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 76 | std::ofstream out; 77 | out.open("example_line_style.svg"); 78 | BackendSVG backend(out); 79 | fig->draw(backend); 80 | out.close(); 81 | #endif 82 | #ifdef TRASE_EXAMPLES_GL_BACKEND 83 | BackendGL backend; 84 | fig->show(backend); 85 | #endif 86 | } 87 | /// [example line style] 88 | -------------------------------------------------------------------------------- /examples/FacetPoints.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_facet_points Facet 35 | /// This is an example of faceting a data set for an animation 36 | /// 37 | /// \image html 38 | /// https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_facet_points.svg 39 | /// "Output" \snippet examples/FacetPoints.cpp example facet points 40 | 41 | /// [example facet points] 42 | #include "trase.hpp" 43 | #include 44 | #include 45 | 46 | using namespace trase; 47 | 48 | int main() { 49 | CSVDownloader dl; 50 | dl.set_delim('\t'); 51 | auto csv = dl.download("https://www.stat.ubc.ca/~jenny/notOcto/STAT545A/" 52 | "examples/gapminder/data/gapminderDataFiveYear.txt"); 53 | 54 | auto fig = figure(); 55 | auto ax = fig->axis(); 56 | auto data = 57 | create_data().x(csv["gdpPercap"]).y(csv["lifeExp"]).size(csv["pop"]).color(csv["continent"]); 58 | 59 | data.x(0, 4e4).y(20, 84); 60 | 61 | auto faceted_data = data.facet(csv["year"]); 62 | 63 | auto facet = faceted_data.begin(); 64 | auto points = ax->points(facet->second); 65 | 66 | int i = 0; 67 | for (;facet != faceted_data.end(); ++facet, ++i) { 68 | points->add_frame(facet->second, i); 69 | } 70 | 71 | ax->xlabel("gdpPercap"); 72 | ax->ylabel("lifeExp"); 73 | 74 | // output to chosen backend 75 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 76 | std::ofstream out; 77 | out.open("example_facet_points.svg"); 78 | BackendSVG backend(out); 79 | fig->draw(backend); 80 | out.close(); 81 | #endif 82 | #ifdef TRASE_EXAMPLES_GL_BACKEND 83 | BackendGL backend; 84 | fig->show(backend); 85 | #endif 86 | } 87 | /// [example facet points] 88 | -------------------------------------------------------------------------------- /src/frontend/Drawable.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "frontend/Drawable.hpp" 35 | 36 | #include "util/Exception.hpp" 37 | 38 | namespace trase { 39 | 40 | Drawable::Drawable(Drawable *parent, const bfloat2_t &area_of_parent) 41 | : m_parent(parent), m_area(area_of_parent), m_time_span(0), m_times({0}) { 42 | if (parent) { 43 | resize(m_parent->m_pixels); 44 | } 45 | } 46 | 47 | void Drawable::resize(const bfloat2_t &parent_pixels) { 48 | m_pixels.bmin = m_area.bmin * parent_pixels.delta() + parent_pixels.min(); 49 | m_pixels.bmax = m_area.bmax * parent_pixels.delta() + parent_pixels.min(); 50 | for (auto &i : m_children) { 51 | i->resize(m_pixels); 52 | } 53 | } 54 | 55 | void Drawable::update_frame_info(const float time) { 56 | 57 | // if time is outside time range clip it 58 | float clipped_time = time; 59 | if (time < 0.f) { 60 | clipped_time = 0.f; 61 | } else if (time > m_time_span) { 62 | clipped_time = m_time_span; 63 | } 64 | 65 | m_frame_info.update(m_times, clipped_time); 66 | } 67 | 68 | const FrameInfo &Drawable::get_frame_info() const { return m_frame_info; } 69 | 70 | void Drawable::add_frame_time(const float time) { 71 | if (time < m_times.back()) { 72 | throw Exception("cannot add frame with time less than max frame time"); 73 | } 74 | m_times.push_back(time); 75 | update_time_span(time); 76 | } 77 | 78 | void Drawable::update_time_span(const float time) { 79 | if (time > m_time_span) { 80 | m_time_span = time; 81 | } 82 | 83 | // need to inform parents 84 | if (m_parent != nullptr) { 85 | m_parent->update_time_span(time); 86 | } 87 | } 88 | 89 | Style &Drawable::style() noexcept { return m_style; } 90 | 91 | } // namespace trase 92 | -------------------------------------------------------------------------------- /tests/TestLegend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include "DummyDraw.hpp" 37 | 38 | #include "trase.hpp" 39 | #include 40 | 41 | using namespace trase; 42 | 43 | TEST_CASE("legend creation", "[legend]") { 44 | auto fig = figure(); 45 | auto ax = fig->axis(); 46 | const int n = 100; 47 | std::vector x(n); 48 | std::vector y(n); 49 | for (int i = 0; i < n; ++i) { 50 | x[i] = 6.28f * static_cast(i) / n; 51 | y[i] = (n / 2) * std::sin(x[i]); 52 | } 53 | auto data = create_data().x(x).y(y); 54 | auto geom = ax->histogram(data); 55 | geom->set_label("histogram"); 56 | DummyDraw::draw("legend", fig); 57 | ax->legend(); 58 | DummyDraw::draw("legend", fig); 59 | geom = ax->line(data); 60 | geom->set_label("line"); 61 | DummyDraw::draw("legend", fig); 62 | geom = ax->points(data); 63 | geom->set_label("points"); 64 | DummyDraw::draw("legend", fig); 65 | } 66 | 67 | TEST_CASE("animated points", "[legend]") { 68 | auto fig = figure(); 69 | auto ax = fig->axis(); 70 | const int n = 100; 71 | std::vector x(n); 72 | std::vector y(n); 73 | std::vector c(n); 74 | 75 | std::vector datas(5); 76 | for (int i = 0; i < 5; ++i) { 77 | for (int j = 0; j < n; ++j) { 78 | x[j] = 6.28f * static_cast(j) / n; 79 | y[j] = (n / 2) * std::sin(x[j]); 80 | c[j] = (n / 2) * std::sin(x[j] + i * 6.28f / 5.f); 81 | } 82 | datas[i].x(x).y(y).color(c); 83 | } 84 | 85 | auto geom = ax->points(datas[0]); 86 | for (int i = 1; i < 5; ++i) { 87 | geom->add_frame(datas[i], static_cast(i) / 5.f); 88 | } 89 | geom->set_label("points"); 90 | ax->legend(); 91 | DummyDraw::draw("legend_animated_points", fig); 92 | } 93 | -------------------------------------------------------------------------------- /examples/Histogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_histogram Animated Histogram Geometry 35 | /// This is an example for the histogram geometry 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_histogram.svg "Output" 38 | /// \snippet examples/Histogram.cpp example histogram 39 | 40 | /// [example histogram] 41 | #include "trase.hpp" 42 | #include 43 | #include 44 | 45 | using namespace trase; 46 | 47 | int main() { 48 | 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | const int n = 100; 52 | std::vector x(n); 53 | std::default_random_engine gen; 54 | std::normal_distribution normal(0, 1); 55 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 56 | 57 | auto data = create_data().x(x); 58 | 59 | auto hist = ax->histogram(data); 60 | hist->set_label("hist"); 61 | 62 | float time = 0.0; 63 | 64 | auto do_plot = [&](const float theta) { 65 | time += 0.3f; 66 | std::normal_distribution normal(theta, 1); 67 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 68 | auto data = create_data().x(x); 69 | hist->add_frame(data, time); 70 | }; 71 | 72 | for (int i = 0; i < 5; ++i) { 73 | const float theta = i / 5.f; 74 | do_plot(theta); 75 | } 76 | 77 | ax->xlabel("x"); 78 | ax->ylabel("y"); 79 | ax->title("histogram test"); 80 | ax->legend(); 81 | 82 | // output to chosen backend 83 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 84 | std::ofstream out; 85 | out.open("example_histogram.svg"); 86 | BackendSVG backend(out); 87 | fig->draw(backend); 88 | out.close(); 89 | #endif 90 | #ifdef TRASE_EXAMPLES_GL_BACKEND 91 | BackendGL backend; 92 | fig->show(backend); 93 | #endif 94 | } 95 | /// [example histogram] 96 | -------------------------------------------------------------------------------- /examples/AnimatedLine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_animated_line Animated Line Geometry 35 | /// This is an example for the line geometry, showing an animated plot 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_animated_line.svg "Output" 38 | /// \snippet examples/AnimatedLine.cpp animated line example 39 | 40 | /// [animated line example] 41 | #include "trase.hpp" 42 | #include 43 | 44 | using namespace trase; 45 | 46 | int main() { 47 | 48 | // create figure and axis 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | 52 | // set x steps, logistic parameter and create x and y vectors 53 | const int n = 100; 54 | const float dx = 12.f / static_cast(n); 55 | const float k = 1.f; 56 | auto logistic = [k](const float x) { return 1.f / (1.f + std::exp(-k * x)); }; 57 | std::vector x = {-6}; 58 | std::vector y = {logistic(x.back())}; 59 | 60 | // create the initial dataset and then plot it using a line geometry 61 | auto data = create_data().x(x).y(y); 62 | auto plt = ax->line(data); 63 | 64 | // loop through rest of the points, generating a new frame for every point 65 | for (int i = 1; i < n; ++i) { 66 | x.push_back(x.back() + dx); 67 | y.push_back(logistic(x.back())); 68 | auto data = create_data().x(x).y(y); 69 | plt->add_frame(data, (x.back() - x[0]) / 4.f); 70 | } 71 | 72 | // label axis 73 | ax->xlabel("x"); 74 | ax->ylabel("y"); 75 | 76 | // output to chosen backend 77 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 78 | std::ofstream out; 79 | out.open("example_animated_line.svg"); 80 | BackendSVG backend(out); 81 | fig->draw(backend); 82 | out.close(); 83 | #endif 84 | #ifdef TRASE_EXAMPLES_GL_BACKEND 85 | BackendGL backend; 86 | fig->show(backend); 87 | #endif 88 | } 89 | /// [animated line example] 90 | -------------------------------------------------------------------------------- /src/frontend/Legend.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | #include "frontend/Legend.hpp" 37 | 38 | namespace trase { 39 | 40 | template 41 | void Legend::draw(AnimatedBackend &backend) { 42 | draw_common(backend, [&](const bfloat2_t &sample_box, 43 | const std::shared_ptr &geometry) { 44 | geometry->dispatch_legend(backend, sample_box); 45 | }); 46 | } 47 | 48 | template 49 | void Legend::draw(Backend &backend, const float time) { 50 | draw_common(backend, [&](const bfloat2_t &sample_box, 51 | const std::shared_ptr &geometry) { 52 | geometry->dispatch_legend(backend, time, sample_box); 53 | }); 54 | } 55 | 56 | template 57 | void Legend::draw_common(Backend &backend, const Callback &callback) { 58 | const float sample_length = 20.f; 59 | 60 | // draw legend in upper right corner 61 | vfloat2_t upper_right_corner = {m_pixels.bmax[0], m_pixels.bmin[1]}; 62 | backend.text_align(ALIGN_RIGHT | ALIGN_TOP); 63 | backend.stroke_width(m_style.line_width()); 64 | backend.fill_color(m_style.color()); 65 | for (const auto &geometry : m_entries) { 66 | const vfloat2_t upper_left_corner = 67 | upper_right_corner - vfloat2_t{sample_length, 0}; 68 | const vfloat2_t lower_right_corner = 69 | upper_right_corner + vfloat2_t{0, m_style.font_size()}; 70 | const bfloat2_t sample_box = {upper_left_corner, lower_right_corner}; 71 | callback(sample_box, geometry); 72 | backend.fill_color(m_style.color()); 73 | backend.text(upper_right_corner + 74 | vfloat2_t(-(5.f / 3.f) * sample_length, 0.f), 75 | geometry->get_label().c_str(), nullptr); 76 | upper_right_corner[1] += m_style.font_size(); 77 | } 78 | } // namespace trase 79 | 80 | } // namespace trase 81 | -------------------------------------------------------------------------------- /tests/TestCSVDownloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include 37 | #include 38 | 39 | #include "trase.hpp" 40 | 41 | using namespace trase; 42 | 43 | TEST_CASE("download test file", "[csv downloader]") { 44 | CSVDownloader dl; 45 | dl.set_delim('\t'); 46 | #ifdef TRASE_HAVE_CURL 47 | auto data = dl.download("https://www.stat.ubc.ca/~jenny/notOcto/STAT545A/" 48 | "examples/gapminder/data/gapminderDataFiveYear.txt"); 49 | std::map expected; 50 | expected["country"] = "Afghanistan"; 51 | expected["year"] = "1952"; 52 | expected["pop"] = "8425333"; 53 | expected["continent"] = "Asia"; 54 | expected["lifeExp"] = "28.801"; 55 | expected["gdpPercap"] = "779.4453145"; 56 | int i = 0; 57 | for (auto it = data.begin(); it != data.end(); ++it, ++i) { 58 | CHECK(it->second[0] == expected[it->first]); 59 | } 60 | CHECK(i == 6); 61 | #else 62 | REQUIRE_THROWS_WITH( 63 | dl.download("https://www.stat.ubc.ca/~jenny/notOcto/STAT545A/" 64 | "examples/gapminder/data/gapminderDataFiveYear.txt"), 65 | Catch::Contains("libcurl not found")); 66 | #endif 67 | } 68 | 69 | TEST_CASE("download test file 2", "[csv downloader]") { 70 | CSVDownloader dl; 71 | #ifdef TRASE_HAVE_CURL 72 | auto data = dl.download( 73 | "http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", 74 | {"sepal_length", "sepal_width", "petal_length", "petal_width", "class"}); 75 | std::map expected; 76 | expected["sepal_length"] = "5.1"; 77 | expected["sepal_width"] = "3.5"; 78 | expected["petal_length"] = "1.4"; 79 | expected["petal_width"] = "0.2"; 80 | expected["class"] = "Iris-setosa"; 81 | int i = 0; 82 | for (auto it = data.begin(); it != data.end(); ++it, ++i) { 83 | CHECK(it->second[0] == expected[it->first]); 84 | } 85 | CHECK(i == 5); 86 | #endif 87 | } 88 | -------------------------------------------------------------------------------- /src/frontend/Line.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Line.hpp 35 | 36 | #ifndef LINE_H_ 37 | #define LINE_H_ 38 | 39 | #include "frontend/Geometry.hpp" 40 | 41 | namespace trase { 42 | 43 | /// A single line made up of one or more points connected by straight lines 44 | /// 45 | /// Aesthetics: 46 | /// - x (x-coordinates of the line points) 47 | /// - y (y-coordinates of the line points) 48 | /// 49 | /// Default Transform: 50 | /// - Identity 51 | class Line : public Geometry { 52 | public: 53 | /// create a new Line, connecting it to the @p parent 54 | explicit Line(Axis *parent) : Geometry(parent) {} 55 | virtual ~Line() = default; 56 | 57 | TRASE_GEOMETRY_DISPATCH_BACKENDS 58 | 59 | /// draw the full line animation using the AnimatedBackend 60 | /// 61 | /// @param backend the AnimatedBackend to use when drawing 62 | template void draw(AnimatedBackend &backend); 63 | 64 | /// draw the line at a snapshot in time using the Backend 65 | /// 66 | /// @param backend the Backend to use when drawing 67 | /// @param time draw the line at this time 68 | template void draw(Backend &backend, float time); 69 | 70 | /// draw the full line legend animation 71 | /// 72 | /// @param backend the AnimatedBackend to use when drawing 73 | template 74 | void draw_legend(AnimatedBackend &backend, const bfloat2_t &box); 75 | 76 | /// draw the line legend at a snapshot in time 77 | /// 78 | /// @param backend the Backend to use when drawing 79 | /// @param time draw the legend at this time 80 | template 81 | void draw_legend(Backend &backend, float time, const bfloat2_t &box); 82 | 83 | private: 84 | template 85 | void draw_frames(AnimatedBackend &backend); 86 | template 87 | void draw_anim_highlights(AnimatedBackend &backend); 88 | template void draw_plot(Backend &backend); 89 | template void draw_highlights(Backend &backend); 90 | }; 91 | 92 | } // namespace trase 93 | 94 | #include "frontend/Line.tcc" 95 | 96 | #endif // LINE_H_ 97 | -------------------------------------------------------------------------------- /src/frontend/Histogram.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Histogram.hpp 35 | 36 | #ifndef HISTOGRAM_H_ 37 | #define HISTOGRAM_H_ 38 | 39 | #include "frontend/Geometry.hpp" 40 | 41 | namespace trase { 42 | 43 | /// A collection of rectangles arranged evenly along the x-axis, with 44 | /// varying heights (i.e. a histogram with regular bins) 45 | /// 46 | /// Aesthetics: 47 | /// - y (the heights of each rectangle) 48 | /// - x (this geometry uses min/max limits only) 49 | /// 50 | /// Default Transform: 51 | /// - BinX 52 | class Histogram : public Geometry { 53 | public: 54 | /// create a new Histogram, connecting it to the @p parent 55 | explicit Histogram(Axis *parent) : Geometry(parent) {} 56 | virtual ~Histogram() = default; 57 | TRASE_GEOMETRY_DISPATCH_BACKENDS 58 | 59 | /// draw the full histogram animation using the AnimatedBackend 60 | /// 61 | /// @param backend the AnimatedBackend to use when drawing 62 | template void draw(AnimatedBackend &backend); 63 | 64 | /// draw the histogram at a snapshot in time using the Backend 65 | /// 66 | /// @param backend the Backend to use when drawing 67 | /// @param time draw the histogram at this time 68 | template void draw(Backend &backend, float time); 69 | 70 | /// draw the full histogram legend animation 71 | /// 72 | /// @param backend the AnimatedBackend to use when drawing 73 | template 74 | void draw_legend(AnimatedBackend &backend, const bfloat2_t &box); 75 | 76 | /// draw the histogram legend at a snapshot in time 77 | /// 78 | /// @param backend the Backend to use when drawing 79 | /// @param time draw the legend at this time 80 | template 81 | void draw_legend(Backend &backend, float time, const bfloat2_t &box); 82 | 83 | private: 84 | template 85 | void draw_frames(AnimatedBackend &backend); 86 | template void draw_plot(Backend &backend); 87 | template void draw_highlights(Backend &backend); 88 | }; 89 | 90 | } // namespace trase 91 | 92 | #include "frontend/Histogram.tcc" 93 | 94 | #endif // LINE_H_ 95 | -------------------------------------------------------------------------------- /src/util/ColumnIterator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file ColumnIterator.hpp 35 | 36 | #ifndef COLUMNITERATOR_H_ 37 | #define COLUMNITERATOR_H_ 38 | 39 | #include 40 | 41 | namespace trase { 42 | 43 | /// A const iterator that iterates through a single column of the raw data class 44 | /// Impliments an random access iterator with a given stride 45 | class ColumnIterator { 46 | public: 47 | using pointer = float const *; 48 | using iterator_category = std::random_access_iterator_tag; 49 | using reference = float const &; 50 | using value_type = float const; 51 | using difference_type = std::ptrdiff_t; 52 | 53 | ColumnIterator() = default; 54 | 55 | ColumnIterator(const std::vector::const_iterator &p, const int stride) 56 | : m_p(&(*p)), m_stride(stride) {} 57 | 58 | reference operator*() const { return dereference(); } 59 | 60 | reference operator->() const { return dereference(); } 61 | 62 | ColumnIterator &operator++() { 63 | increment(); 64 | return *this; 65 | } 66 | 67 | const ColumnIterator operator++(int) { 68 | ColumnIterator tmp(*this); 69 | operator++(); 70 | return tmp; 71 | } 72 | 73 | ColumnIterator operator+(int n) const { 74 | ColumnIterator tmp(*this); 75 | tmp.increment(n); 76 | return tmp; 77 | } 78 | 79 | reference operator[](const int i) const { return operator+(i).dereference(); } 80 | 81 | size_t operator-(const ColumnIterator &start) const { 82 | return (m_p - start.m_p) / m_stride; 83 | } 84 | 85 | inline bool operator==(const ColumnIterator &rhs) const { return equal(rhs); } 86 | 87 | inline bool operator!=(const ColumnIterator &rhs) const { 88 | return !operator==(rhs); 89 | } 90 | 91 | private: 92 | bool equal(ColumnIterator const &other) const { return m_p == other.m_p; } 93 | 94 | reference dereference() const { return *m_p; } 95 | 96 | void increment() { std::advance(m_p, m_stride); } 97 | 98 | void increment(const int n) { std::advance(m_p, n * m_stride); } 99 | 100 | pointer m_p; 101 | int m_stride; 102 | }; 103 | 104 | } // namespace trase 105 | 106 | #endif // COLUMNITERATOR_H_ 107 | -------------------------------------------------------------------------------- /examples/AnimatedPoints.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \page example_animated_points Animated Points Geometry 35 | /// This is an example for the points geometry 36 | /// 37 | /// \image html https://cdn.jsdelivr.net/gh/trase-cpp/generated_files@master/examples/example_animated_points.svg "Output" 38 | /// \snippet examples/AnimatedPoints.cpp example animated points 39 | 40 | /// [example animated points] 41 | #include "trase.hpp" 42 | #include 43 | #include 44 | 45 | using namespace trase; 46 | 47 | int main() { 48 | 49 | auto fig = figure(); 50 | auto ax = fig->axis(); 51 | const int n = 100; 52 | std::vector x(n), y(n), r(n), c(n); 53 | std::default_random_engine gen; 54 | std::normal_distribution normal(0, 1); 55 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 56 | std::generate(y.begin(), y.end(), [&]() { return normal(gen); }); 57 | std::generate(r.begin(), r.end(), [&]() { return normal(gen); }); 58 | std::generate(c.begin(), c.end(), [&]() { return normal(gen); }); 59 | 60 | auto data = create_data().x(x).y(y).size(r).color(c); 61 | 62 | auto points = ax->points(data); 63 | points->set_label("points"); 64 | 65 | float time = 0.0; 66 | 67 | auto do_plot = [&]() { 68 | time += 0.3f; 69 | std::normal_distribution normal(0, 1); 70 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 71 | std::generate(y.begin(), y.end(), [&]() { return normal(gen); }); 72 | std::generate(r.begin(), r.end(), [&]() { return normal(gen); }); 73 | std::generate(c.begin(), c.end(), [&]() { return normal(gen); }); 74 | auto data = create_data().x(x).y(y).size(r).color(c); 75 | points->add_frame(data, time); 76 | }; 77 | 78 | for (int i = 0; i < 5; ++i) { 79 | do_plot(); 80 | } 81 | 82 | ax->xlabel("x"); 83 | ax->ylabel("y"); 84 | ax->title("points test"); 85 | ax->legend(); 86 | 87 | // output to chosen backend 88 | #ifdef TRASE_EXAMPLES_SVG_BACKEND 89 | std::ofstream out; 90 | out.open("example_animated_points.svg"); 91 | BackendSVG backend(out); 92 | fig->draw(backend); 93 | out.close(); 94 | #endif 95 | #ifdef TRASE_EXAMPLES_GL_BACKEND 96 | BackendGL backend; 97 | fig->show(backend); 98 | #endif 99 | } 100 | /// [example animated points] 101 | -------------------------------------------------------------------------------- /tests/TestTransformMatrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include 37 | #include 38 | 39 | #include "backend/Backend.hpp" 40 | 41 | TEST_CASE("constructors", "[transform matrix]") { 42 | 43 | // Default construction 44 | trase::TransformMatrix t; 45 | 46 | // check identity 47 | CHECK(t.is_identity() == true); 48 | 49 | /// [a c e] [1 0 0] 50 | /// [b d f] = [0 1 0] 51 | /// [0 0 1] [0 0 1] 52 | 53 | CHECK(t.a == 1.f); 54 | CHECK(t.b == 0.f); 55 | CHECK(t.c == 0.f); 56 | CHECK(t.d == 1.f); 57 | CHECK(t.e == 0.f); 58 | CHECK(t.f == 0.f); 59 | } 60 | 61 | TEST_CASE("to_string", "[transform matrix]") { 62 | 63 | // Default construction 64 | trase::TransformMatrix t; 65 | 66 | CHECK(t.to_string() == "transform=\"matrix(1 0 0 1 0 0)\""); 67 | } 68 | 69 | TEST_CASE("translations", "[transform matrix]") { 70 | 71 | trase::TransformMatrix t; 72 | 73 | /// [a c e] [1 0 0] 74 | /// [b d f] = [0 1 1] 75 | /// [0 0 1] [0 0 1] 76 | t.translate({0.f, 1.f}); 77 | 78 | CHECK(t.a == 1.f); 79 | CHECK(t.b == 0.f); 80 | CHECK(t.c == 0.f); 81 | CHECK(t.d == 1.f); 82 | CHECK(t.e == 0.f); 83 | CHECK(t.f == 1.f); 84 | 85 | /// [a c e] [1 0 1] 86 | /// [b d f] = [0 1 1] 87 | /// [0 0 1] [0 0 1] 88 | t.translate({1.f, 0.f}); 89 | 90 | CHECK(t.a == 1.f); 91 | CHECK(t.b == 0.f); 92 | CHECK(t.c == 0.f); 93 | CHECK(t.d == 1.f); 94 | CHECK(t.e == 1.f); 95 | CHECK(t.f == 1.f); 96 | } 97 | 98 | TEST_CASE("rotations", "[transform matrix]") { 99 | 100 | trase::TransformMatrix t; 101 | 102 | /// [a c e] [-1 0 0] 103 | /// [b d f] = [0 -1 0] 104 | /// [0 0 1] [0 0 1] 105 | t.rotate(trase::pi); 106 | 107 | CHECK(t.a == Approx(-1.f)); 108 | CHECK(t.b == Approx(0.0f).margin(1e-7)); 109 | CHECK(t.c == Approx(0.0f).margin(1e-7)); 110 | CHECK(t.d == Approx(-1.f)); 111 | CHECK(t.e == Approx(0.f)); 112 | CHECK(t.f == Approx(0.f)); 113 | 114 | /// [a c e] [1 0 0] 115 | /// [b d f] = [0 1 0] 116 | /// [0 0 1] [0 0 1] 117 | t.rotate(-trase::pi); 118 | 119 | CHECK(t.a == Approx(1.f)); 120 | CHECK(t.b == Approx(0.f)); 121 | CHECK(t.c == Approx(0.f)); 122 | CHECK(t.d == Approx(1.f)); 123 | CHECK(t.e == Approx(0.f)); 124 | CHECK(t.f == Approx(0.f)); 125 | } 126 | -------------------------------------------------------------------------------- /src/frontend/Points.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Points.hpp 35 | 36 | #ifndef POINTS_H_ 37 | #define POINTS_H_ 38 | 39 | #include "frontend/Geometry.hpp" 40 | 41 | namespace trase { 42 | 43 | /// A collection of one or more filled circles 44 | /// 45 | /// Aesthetics: 46 | /// - x (x-coordinate of circle centres) 47 | /// - y (y-coordinate of circle centres) 48 | /// - size (optional - radius of circles) 49 | /// - color (optional - fill color of circles) 50 | /// 51 | /// Note that the circles have no separate stroke color for their outer 52 | /// circumference, they are single solid color 53 | /// 54 | /// Default Transform: 55 | /// - Identity 56 | class Points : public Geometry { 57 | public: 58 | /// create a new Points, connecting it to the @p parent 59 | explicit Points(Axis *parent) : Geometry(parent) {} 60 | 61 | virtual ~Points() = default; 62 | 63 | TRASE_GEOMETRY_DISPATCH_BACKENDS 64 | 65 | /// draw the full points animation using the AnimatedBackend 66 | /// 67 | /// @param backend the AnimatedBackend to use when drawing 68 | template void draw(AnimatedBackend &backend); 69 | 70 | /// draw the points at a snapshot in time using the Backend 71 | /// 72 | /// @param backend the Backend to use when drawing 73 | /// @param time draw the points at this time 74 | template void draw(Backend &backend, float time); 75 | 76 | /// draw the full points legend animation 77 | /// 78 | /// @param backend the AnimatedBackend to use when drawing 79 | template 80 | void draw_legend(AnimatedBackend &backend, const bfloat2_t &box); 81 | 82 | /// draw the points legend at a snapshot in time 83 | /// 84 | /// @param backend the Backend to use when drawing 85 | /// @param time draw the legend at this time 86 | template 87 | void draw_legend(Backend &backend, float time, const bfloat2_t &box); 88 | 89 | private: 90 | void validate_frames(const bool have_size, const bool have_color, 91 | const int n); 92 | template 93 | void draw_frames(AnimatedBackend &backend); 94 | template void draw_plot(Backend &backend); 95 | }; 96 | 97 | } // namespace trase 98 | 99 | #include "frontend/Points.tcc" 100 | 101 | #endif // POINTS_H_ 102 | -------------------------------------------------------------------------------- /tests/TestHistogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include "DummyDraw.hpp" 37 | 38 | //! [histogram example includes] 39 | #include "trase.hpp" 40 | #include 41 | #include 42 | //! [histogram example includes] 43 | 44 | using namespace trase; 45 | 46 | TEST_CASE("histogram example", "[histogram]") { 47 | /// \page line_example Example of using the histogram geometry 48 | /// This is an example for the histogram geometry 49 | /// 50 | /// \snippet tests/TestHistogram.cpp histogram example includes 51 | /// \snippet tests/TestHistogram.cpp histogram example 52 | 53 | /// [histogram example] 54 | auto fig = figure(); 55 | auto ax = fig->axis(); 56 | const int n = 100; 57 | std::vector x(n); 58 | std::default_random_engine gen; 59 | std::normal_distribution normal(0, 1); 60 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 61 | 62 | auto data = create_data().x(x); 63 | 64 | auto hist = ax->histogram(data); 65 | hist->set_label("hist"); 66 | 67 | float time = 0.0; 68 | 69 | auto do_plot = [&](const float theta) { 70 | time += 0.3f; 71 | std::normal_distribution normal(theta, 1); 72 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 73 | auto data = create_data().x(x); 74 | hist->add_frame(data, time); 75 | }; 76 | 77 | for (int i = 0; i < 5; ++i) { 78 | const float theta = i / 5.f; 79 | do_plot(theta); 80 | } 81 | 82 | ax->xlabel("x"); 83 | ax->ylabel("y"); 84 | ax->title("histogram test"); 85 | ax->legend(); 86 | 87 | // output to svg 88 | std::ofstream out; 89 | out.open("example_histogram.svg"); 90 | BackendSVG backend(out); 91 | fig->draw(backend); 92 | out.close(); 93 | /// [histogram example] 94 | } 95 | 96 | TEST_CASE("histogram creation", "[histogram]") { 97 | auto fig = figure(); 98 | auto ax = fig->axis(); 99 | std::vector x; 100 | ax->histogram(create_data().x(x)); 101 | DummyDraw::draw("histogram", fig); 102 | x.resize(1); 103 | x[0] = 0.1f; 104 | ax->histogram(create_data().x(x)); 105 | DummyDraw::draw("histogram", fig); 106 | x.resize(5); 107 | x[1] = 0.2f; 108 | x[2] = 0.3f; 109 | x[3] = 0.4f; 110 | x[4] = 0.5f; 111 | ax->histogram(create_data().x(x)); 112 | DummyDraw::draw("histogram", fig); 113 | } 114 | -------------------------------------------------------------------------------- /src/frontend/Rectangle.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Rectangle.hpp 35 | 36 | #ifndef RECTANGLE_H_ 37 | #define RECTANGLE_H_ 38 | 39 | #include "frontend/Geometry.hpp" 40 | 41 | namespace trase { 42 | 43 | /// A collection of one or more filled rectangles 44 | /// 45 | /// Aesthetics: 46 | /// - xmin (minimum x-coordinate of rectangles) 47 | /// - ymin (minimum y-coordinate of rectangles) 48 | /// - xmax (maximum x-coordinate of rectangles) 49 | /// - ymax (maximum y-coordinate of rectangles) 50 | /// - color (optional - stroke color of circles) 51 | /// - fill (optional - fill color of circles) 52 | /// 53 | /// Default Transform: 54 | /// - Identity 55 | class Rectangle : public Geometry { 56 | public: 57 | /// create a new Rectangle, connecting it to the @p parent 58 | explicit Rectangle(Axis *parent) : Geometry(parent) {} 59 | 60 | virtual ~Rectangle() = default; 61 | 62 | TRASE_GEOMETRY_DISPATCH_BACKENDS 63 | 64 | /// draw the full rectangles animation using the AnimatedBackend 65 | /// 66 | /// @param backend the AnimatedBackend to use when drawing 67 | template void draw(AnimatedBackend &backend); 68 | 69 | /// draw the rectangles at a snapshot in time using the Backend 70 | /// 71 | /// @param backend the Backend to use when drawing 72 | /// @param time draw the rectangles at this time 73 | template void draw(Backend &backend, float time); 74 | 75 | /// draw the full rectangle legend animation 76 | /// 77 | /// @param backend the AnimatedBackend to use when drawing 78 | template 79 | void draw_legend(AnimatedBackend &backend, const bfloat2_t &box); 80 | 81 | /// draw the rectangles legend at a snapshot in time 82 | /// 83 | /// @param backend the Backend to use when drawing 84 | /// @param time draw the legend at this time 85 | template 86 | void draw_legend(Backend &backend, float time, const bfloat2_t &box); 87 | 88 | private: 89 | void validate_frames(const bool have_color, const bool have_fill, 90 | const int n); 91 | template 92 | void draw_frames(AnimatedBackend &backend); 93 | template void draw_plot(Backend &backend); 94 | }; 95 | 96 | } // namespace trase 97 | 98 | #include "frontend/Rectangle.tcc" 99 | 100 | #endif // RECTANGLE_H_ 101 | -------------------------------------------------------------------------------- /tests/TestColors.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include "util/Colors.hpp" 37 | 38 | TEST_CASE("color construction", "[colors]") { 39 | 40 | trase::RGBA b{1,2,3}; 41 | trase::RGBA c{1,2,3, trase::RGBA::default_alpha}; 42 | 43 | CHECK(b == c); 44 | } 45 | 46 | TEST_CASE("color setters and getters", "[colors]") { 47 | 48 | trase::RGBA my_col{4, 5, 6, 7}; 49 | 50 | CHECK(my_col.r() == 4); 51 | CHECK(my_col.g() == 5); 52 | CHECK(my_col.b() == 6); 53 | CHECK(my_col.a() == 7); 54 | 55 | my_col.r(12).g(13).b(15).a(21); 56 | 57 | CHECK(my_col.r() == 12); 58 | CHECK(my_col.g() == 13); 59 | CHECK(my_col.b() == 15); 60 | CHECK(my_col.a() == 21); 61 | } 62 | 63 | TEST_CASE("color to string", "[colors]") { 64 | 65 | CHECK(trase::RGBA::black.to_rgb_string() == "#000000"); 66 | CHECK(trase::RGBA::white.to_rgb_string() == "#ffffff"); 67 | } 68 | 69 | TEST_CASE("color equality operators", "[colors]") { 70 | 71 | CHECK(trase::RGBA::black == trase::RGBA::black); 72 | CHECK(trase::RGBA::white == trase::RGBA::white); 73 | 74 | CHECK(trase::RGBA::black != trase::RGBA::white); 75 | CHECK(trase::RGBA::white != trase::RGBA::black); 76 | 77 | CHECK(!(trase::RGBA::black == trase::RGBA::white)); 78 | CHECK(!(trase::RGBA::white == trase::RGBA::black)); 79 | } 80 | 81 | TEST_CASE("color statics", "[colors]") { 82 | 83 | CHECK(trase::RGBA::default_alpha == 200); 84 | 85 | trase::RGBA black = trase::RGBA::black; 86 | CHECK(black.r() == 0); 87 | CHECK(black.g() == 0); 88 | CHECK(black.b() == 0); 89 | CHECK(black.a() == trase::RGBA::default_alpha); 90 | 91 | trase::RGBA white = trase::RGBA::white; 92 | CHECK(white.r() == 255); 93 | CHECK(white.g() == 255); 94 | CHECK(white.b() == 255); 95 | CHECK(white.a() == trase::RGBA::default_alpha); 96 | 97 | CHECK(trase::RGBA::defaults.at(0) == trase::RGBA{31, 119, 180}); 98 | CHECK(trase::RGBA::defaults.at(1) == trase::RGBA{255, 127, 14}); 99 | CHECK(trase::RGBA::defaults.at(2) == trase::RGBA{44, 160, 44}); 100 | CHECK(trase::RGBA::defaults.at(3) == trase::RGBA{214, 39, 40}); 101 | CHECK(trase::RGBA::defaults.at(4) == trase::RGBA{148, 103, 189}); 102 | CHECK(trase::RGBA::defaults.at(5) == trase::RGBA{140, 86, 75}); 103 | CHECK(trase::RGBA::defaults.at(6) == trase::RGBA{227, 119, 194}); 104 | CHECK(trase::RGBA::defaults.at(7) == trase::RGBA{127, 127, 127}); 105 | CHECK(trase::RGBA::defaults.at(8) == trase::RGBA{188, 189, 34}); 106 | CHECK(trase::RGBA::defaults.at(9) == trase::RGBA{23, 190, 207}); 107 | } 108 | -------------------------------------------------------------------------------- /src/frontend/Figure.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "frontend/Figure.hpp" 35 | 36 | #include 37 | #include 38 | 39 | #include "util/BBox.hpp" 40 | #include "util/Vector.hpp" 41 | 42 | namespace trase { 43 | 44 | int Figure::m_num_windows = 0; 45 | 46 | Figure::Figure(const std::array &pixels) 47 | : Drawable(nullptr, 48 | bfloat2_t(vfloat2_t(0, 0), vfloat2_t(pixels[0], pixels[1]))), 49 | m_id(++m_num_windows), m_axis_layout{0, 0} { 50 | m_pixels = m_area; 51 | } 52 | 53 | std::shared_ptr Figure::update_layout(const vint2_t &new_position) { 54 | // only allow positive layout positions 55 | if ((new_position < vint2_t{0, 0}).any()) { 56 | throw std::out_of_range("Subplot layout position must be non-negative."); 57 | } 58 | 59 | // determine new layout size 60 | bool resize = false; 61 | for (int i = 0; i < 2; ++i) { 62 | if (m_axis_layout[i] < new_position[i] + 1) { 63 | resize = true; 64 | m_axis_layout[i] = new_position[i] + 1; 65 | } 66 | } 67 | 68 | // if layout changed then resize all children 69 | vfloat2_t axis_size = vfloat2_t{1.0f, 1.0f} / m_axis_layout.cast(); 70 | if (resize) { 71 | for (auto &subplot : m_axis_subplots) { 72 | vfloat2_t position_from_lower_left = { 73 | static_cast(subplot.first[0]), 74 | static_cast(m_axis_layout[1] - subplot.first[1] - 1)}; 75 | subplot.second->area().bmin = 76 | (position_from_lower_left + 0.1f) * axis_size; 77 | subplot.second->area().bmax = 78 | (position_from_lower_left + 0.9f) * axis_size; 79 | subplot.second->resize(m_pixels); 80 | } 81 | } 82 | 83 | // insert new axis into layout or get existing 84 | vfloat2_t position_from_lower_left = { 85 | static_cast(new_position[0]), 86 | static_cast(m_axis_layout[1] - new_position[1] - 1)}; 87 | 88 | bfloat2_t bounding_box((position_from_lower_left + 0.1f) * axis_size, 89 | (position_from_lower_left + 0.9f) * axis_size); 90 | auto result = 91 | m_axis_subplots 92 | .insert(std::make_pair(new_position, 93 | std::make_shared(this, bounding_box))) 94 | .first; 95 | result->second->resize(m_pixels); 96 | 97 | // return the actual shared_ptr to the Axis 98 | return result->second; 99 | } 100 | 101 | std::shared_ptr Figure::axis() { return axis(0, 0); } 102 | 103 | std::shared_ptr Figure::axis(int i, int j) { 104 | auto new_axis = update_layout({j, i}); 105 | m_children.push_back(new_axis); 106 | return new_axis; 107 | } 108 | 109 | } // namespace trase 110 | -------------------------------------------------------------------------------- /src/util/Colors.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Colors.hpp 35 | 36 | #ifndef COLORS_H_ 37 | #define COLORS_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "util/Vector.hpp" 44 | 45 | namespace trase { 46 | 47 | /// Colour class with red, green, blue and alpha in range 0 to 255 48 | class RGBA { 49 | 50 | /// red value 51 | int m_r; 52 | 53 | /// green value 54 | int m_g; 55 | 56 | /// blue value 57 | int m_b; 58 | 59 | /// alpha value 60 | int m_a; 61 | 62 | public: 63 | const static int default_alpha; 64 | const static std::array defaults; 65 | const static RGBA black; 66 | const static RGBA white; 67 | 68 | /// default constructor 69 | RGBA() = default; 70 | 71 | /// constructor taking red, green, blue and alpha 72 | RGBA(int r, int g, int b, int a = default_alpha) noexcept; 73 | 74 | /// constructor taking 4 float vector 75 | explicit RGBA(const Vector &v) noexcept; 76 | 77 | /// constructor taking 3 float vector 78 | explicit RGBA(const Vector &v) noexcept; 79 | 80 | /// convert to an float vector 81 | explicit operator Vector() const noexcept { 82 | return {static_cast(m_r), static_cast(m_g), 83 | static_cast(m_b), static_cast(m_a)}; 84 | }; 85 | 86 | /// convert to an rgb string of form #rrggbb 87 | std::string to_rgb_string() const noexcept; 88 | 89 | /// Get the current red value 90 | int r() const noexcept; 91 | 92 | /// Get the current green value 93 | int g() const noexcept; 94 | 95 | /// Get the current blue value 96 | int b() const noexcept; 97 | 98 | /// Get the current alpha value 99 | int a() const noexcept; 100 | 101 | /// Set a new red value 102 | RGBA &r(int r) noexcept; 103 | 104 | /// Set a new green value 105 | RGBA &g(int g) noexcept; 106 | 107 | /// Set a new blue value 108 | RGBA &b(int b) noexcept; 109 | 110 | /// Set a new alpha value 111 | RGBA &a(int a) noexcept; 112 | 113 | /// Equality comparison 114 | bool operator==(const RGBA &b) const noexcept; 115 | bool operator!=(const RGBA &b) const noexcept; 116 | }; 117 | 118 | /// a linear segmented colormap 119 | class Colormap { 120 | std::vector> m_colors; 121 | 122 | public: 123 | /// constructs the colormap from a list of rgb values scaled from 0-1 124 | explicit Colormap(std::vector> list) noexcept; 125 | 126 | /// maps a float from 0->1 to a RGBA color 127 | RGBA to_color(float i) const; 128 | }; 129 | 130 | struct Colormaps { 131 | static const Colormap viridis; 132 | }; 133 | 134 | } // namespace trase 135 | 136 | #endif // COLORS_H_ 137 | -------------------------------------------------------------------------------- /.codedocs: -------------------------------------------------------------------------------- 1 | # CodeDocs.xyz Configuration File 2 | 3 | DOXYFILE = docs/Doxyfile 4 | 5 | #--------------------------------------------------------------------------- 6 | # Doxygen Configuration 7 | #--------------------------------------------------------------------------- 8 | 9 | # Doxygen configuration may also be placed in this file. 10 | # Currently, the following Doxygen configuration options are available. Refer 11 | # to http://doxygen.org/manual/config.html for detailed explanation of the 12 | # options. To request support for more options, contact support@codedocs.xyz. 13 | # 14 | # ABBREVIATE_BRIEF = 15 | # ALIASES = 16 | # ALLEXTERNALS = 17 | # ALLOW_UNICODE_NAMES = 18 | # ALPHABETICAL_INDEX = 19 | # ALWAYS_DETAILED_SEC = 20 | # AUTOLINK_SUPPORT = 21 | # BRIEF_MEMBER_DESC = 22 | # BUILTIN_STL_SUPPORT = 23 | # CALLER_GRAPH = 24 | # CALL_GRAPH = 25 | # CASE_SENSE_NAMES = 26 | # CITE_BIB_FILES = 27 | # CLASS_DIAGRAMS = 28 | # CLASS_GRAPH = 29 | # COLLABORATION_GRAPH = 30 | # COLS_IN_ALPHA_INDEX = 31 | # CPP_CLI_SUPPORT = 32 | # DIAFILE_DIRS = 33 | # DIRECTORY_GRAPH = 34 | # DISABLE_INDEX = 35 | # DISTRIBUTE_GROUP_DOC = 36 | # DOTFILE_DIRS = 37 | # DOT_FONTNAME = 38 | # DOT_FONTSIZE = 39 | # DOT_GRAPH_MAX_NODES = 40 | # DOT_IMAGE_FORMAT = 41 | # DOT_TRANSPARENT = 42 | # DOXYFILE_ENCODING = 43 | # ENABLED_SECTIONS = 44 | # ENABLE_PREPROCESSING = 45 | # ENUM_VALUES_PER_LINE = 46 | # EXAMPLE_PATH = 47 | # EXAMPLE_PATTERNS = 48 | # EXAMPLE_RECURSIVE = 49 | # EXCLUDE = 50 | # EXCLUDE_PATTERNS = 51 | # EXCLUDE_SYMBOLS = 52 | # EXPAND_AS_DEFINED = 53 | # EXPAND_ONLY_PREDEF = 54 | # EXTENSION_MAPPING = 55 | # EXTERNAL_GROUPS = 56 | # EXTERNAL_PAGES = 57 | # EXTRACT_ALL = 58 | # EXTRACT_ANON_NSPACES = 59 | # EXTRACT_LOCAL_CLASSES = 60 | # EXTRACT_LOCAL_METHODS = 61 | # EXTRACT_PACKAGE = 62 | # EXTRACT_PRIVATE = 63 | # EXTRACT_STATIC = 64 | # EXT_LINKS_IN_WINDOW = 65 | # FILE_PATTERNS = 66 | # FORCE_LOCAL_INCLUDES = 67 | # FORMULA_FONTSIZE = 68 | # FORMULA_TRANSPARENT = 69 | # FULL_PATH_NAMES = 70 | # GENERATE_BUGLIST = 71 | # GENERATE_DEPRECATEDLIST = 72 | # GENERATE_LEGEND = 73 | # GENERATE_TESTLIST = 74 | # GENERATE_TODOLIST = 75 | # GENERATE_TREEVIEW = 76 | # GRAPHICAL_HIERARCHY = 77 | # GROUP_GRAPHS = 78 | # GROUP_NESTED_COMPOUNDS = 79 | # HIDE_COMPOUND_REFERENCE= = 80 | # HIDE_FRIEND_COMPOUNDS = 81 | # HIDE_IN_BODY_DOCS = 82 | # HIDE_SCOPE_NAMES = 83 | # HIDE_UNDOC_CLASSES = 84 | # HIDE_UNDOC_MEMBERS = 85 | # HIDE_UNDOC_RELATIONS = 86 | # HTML_COLORSTYLE_GAMMA = 87 | # HTML_COLORSTYLE_HUE = 88 | # HTML_COLORSTYLE_SAT = 89 | # HTML_DYNAMIC_SECTIONS = 90 | # HTML_EXTRA_FILES = 91 | # HTML_EXTRA_STYLESHEET = 92 | # HTML_FOOTER = 93 | # HTML_HEADER = 94 | # HTML_INDEX_NUM_ENTRIES = 95 | # HTML_STYLESHEET = 96 | # HTML_TIMESTAMP = 97 | # IDL_PROPERTY_SUPPORT = 98 | # IGNORE_PREFIX = 99 | # IMAGE_PATH = 100 | # INCLUDED_BY_GRAPH = 101 | # INCLUDE_FILE_PATTERNS = 102 | # INCLUDE_GRAPH = 103 | # INCLUDE_PATH = 104 | # INHERIT_DOCS = 105 | # INLINE_GROUPED_CLASSES = 106 | # INLINE_INFO = 107 | # INLINE_INHERITED_MEMB = 108 | # INLINE_SIMPLE_STRUCTS = 109 | # INLINE_SOURCES = 110 | # INPUT = 111 | # INPUT_ENCODING = 112 | # INTERACTIVE_SVG = 113 | # INTERNAL_DOCS = 114 | # JAVADOC_AUTOBRIEF = 115 | # LAYOUT_FILE = 116 | # MACRO_EXPANSION = 117 | # MARKDOWN_SUPPORT = 118 | # MAX_DOT_GRAPH_DEPTH = 119 | # MSCFILE_DIRS = 120 | # MULTILINE_CPP_IS_BRIEF = 121 | # OPTIMIZE_FOR_FORTRAN = 122 | # OPTIMIZE_OUTPUT_FOR_C = 123 | # OPTIMIZE_OUTPUT_JAVA = 124 | # OPTIMIZE_OUTPUT_VHDL = 125 | # OUTPUT_LANGUAGE = 126 | # PLANTUML_JAR_PATH = 127 | # PREDEFINED = 128 | # PROJECT_BRIEF = 129 | # PROJECT_LOGO = 130 | # PROJECT_NAME = 131 | # PROJECT_NUMBER = 132 | # QT_AUTOBRIEF = 133 | # RECURSIVE = 134 | # REFERENCED_BY_RELATION = 135 | # REFERENCES_LINK_SOURCE = 136 | # REFERENCES_RELATION = 137 | # REPEAT_BRIEF = 138 | # SEARCHENGINE = 139 | # SEARCH_INCLUDES = 140 | # SEPARATE_MEMBER_PAGES = 141 | # SHORT_NAMES = 142 | # SHOW_FILES = 143 | # SHOW_GROUPED_MEMB_INC = 144 | # SHOW_INCLUDE_FILES = 145 | # SHOW_NAMESPACES = 146 | # SHOW_USED_FILES = 147 | # SIP_SUPPORT = 148 | # SKIP_FUNCTION_MACROS = 149 | # SORT_BRIEF_DOCS = 150 | # SORT_BY_SCOPE_NAME = 151 | # SORT_GROUP_NAMES = 152 | # SORT_MEMBERS_CTORS_1ST = 153 | # SORT_MEMBER_DOCS = 154 | # SOURCE_BROWSER = 155 | # SOURCE_TOOLTIPS = 156 | # STRICT_PROTO_MATCHING = 157 | # STRIP_CODE_COMMENTS = 158 | # STRIP_FROM_INC_PATH = 159 | # STRIP_FROM_PATH = 160 | # SUBGROUPING = 161 | # TAB_SIZE = 162 | # TEMPLATE_RELATIONS = 163 | # TREEVIEW_WIDTH = 164 | # TYPEDEF_HIDES_STRUCT = 165 | # UML_LIMIT_NUM_FIELDS = 166 | # UML_LOOK = 167 | # USE_MDFILE_AS_MAINPAGE = 168 | # VERBATIM_HEADERS = 169 | # 170 | -------------------------------------------------------------------------------- /tests/TestInteractive.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | // This tells Catch to provide a main() - only do this in one cpp file 35 | #define CATCH_CONFIG_MAIN 36 | #include "catch.hpp" 37 | 38 | #include 39 | #include 40 | 41 | #include "trase.hpp" 42 | 43 | using namespace trase; 44 | 45 | // This tests the output of the `get_nth_prime` function 46 | TEST_CASE("interactive test (only run by a human)", "[interactive]") { 47 | 48 | auto fig = figure(); 49 | auto ax = fig->axis(); 50 | const int n = 100; 51 | std::vector x(n); 52 | std::vector y(n); 53 | std::vector r(n); 54 | for (int i = 0; i < n; ++i) { 55 | x[i] = static_cast(i) * 6.28 / n; 56 | y[i] = std::sin(5 * x[i]); 57 | r[i] = 0.1; 58 | } 59 | auto data = create_data().x(x).y(y).color(r).size(r); 60 | auto static_plot = ax->line(data); 61 | static_plot->set_label("static"); 62 | auto moving_plot = ax->line(data); 63 | moving_plot->set_label("moving"); 64 | 65 | auto points = ax->points(data); 66 | points->set_label("points"); 67 | 68 | float time = 0.0; 69 | 70 | auto do_plot = [&](const float theta) { 71 | time += 0.3; 72 | for (int i = 0; i < n; ++i) { 73 | y[i] = std::sin(theta * x[i]); 74 | r[i] = time * 0.1; 75 | } 76 | auto data = create_data().x(x).y(y).color(r).size(r); 77 | moving_plot->add_frame(data, time); 78 | points->add_frame(data, time); 79 | }; 80 | 81 | for (int i = 0; i < 5; ++i) { 82 | const float theta = 5 - i; 83 | do_plot(theta); 84 | } 85 | for (int i = 4; i >= 0; --i) { 86 | const float theta = 5 - i; 87 | do_plot(theta); 88 | } 89 | 90 | ax->xlabel("x"); 91 | ax->ylabel("y"); 92 | ax->title("the interactive test"); 93 | ax->legend(); 94 | 95 | BackendGL backend; 96 | fig->show(backend); 97 | } 98 | 99 | TEST_CASE("histogram", "[interactive]") { 100 | 101 | auto fig = figure(); 102 | auto ax = fig->axis(); 103 | const int n = 100; 104 | std::vector x(n); 105 | std::default_random_engine gen; 106 | std::normal_distribution normal(0, 1); 107 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 108 | 109 | auto data = create_data().x(x); 110 | 111 | auto hist = ax->histogram(data); 112 | hist->set_label("hist"); 113 | 114 | float time = 0.0; 115 | 116 | auto do_plot = [&](const float theta) { 117 | time += 0.3; 118 | std::normal_distribution normal(theta, 1); 119 | std::generate(x.begin(), x.end(), [&]() { return normal(gen); }); 120 | auto data = create_data().x(x); 121 | hist->add_frame(data, time); 122 | }; 123 | 124 | for (int i = 0; i < 5; ++i) { 125 | const float theta = i / 5.f; 126 | do_plot(theta); 127 | } 128 | 129 | ax->xlabel("x"); 130 | ax->ylabel("y"); 131 | ax->title("histogram test"); 132 | ax->legend(); 133 | 134 | BackendGL backend; 135 | fig->show(backend); 136 | } 137 | -------------------------------------------------------------------------------- /src/frontend/Transform.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "frontend/Transform.hpp" 41 | 42 | namespace trase { 43 | 44 | BinX::BinX(const int number_of_bins) : m_number_of_bins(number_of_bins) {} 45 | BinX::BinX(const int number_of_bins, const float min, const float max) 46 | : m_number_of_bins(number_of_bins), 47 | m_span(Vector(min), Vector({max})) {} 48 | 49 | DataWithAesthetic BinX::operator()(const DataWithAesthetic &data) { 50 | auto x_begin = data.begin(); 51 | auto x_end = data.end(); 52 | 53 | // if input data is empty then create an empty y aesthetic 54 | if (std::distance(x_begin, x_end) == 0) { 55 | std::vector y; 56 | return create_data().y(y); 57 | } 58 | 59 | auto minmax = std::minmax_element(x_begin, x_end); 60 | 61 | if (m_span.is_empty()) { 62 | // increase the span slightly so round-off doesn't cause points to fall 63 | // outside the domain 64 | m_span.bmin[0] = 65 | *minmax.first - 1e4f * std::numeric_limits::epsilon(); 66 | m_span.bmin[1] = 67 | *minmax.second + 1e4f * std::numeric_limits::epsilon(); 68 | } 69 | 70 | if (m_number_of_bins == -1) { 71 | auto sum = std::accumulate(x_begin, x_end, 0.f); 72 | auto mean = sum / data.rows(); 73 | 74 | // note: use std::transform_reduce after c++17 75 | std::vector diff(data.rows()); 76 | std::transform(x_begin, x_end, diff.begin(), 77 | [mean](float x) { return x - mean; }); 78 | auto sq_sum = 79 | std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.f); 80 | auto stdev = std::sqrt(sq_sum / data.rows()); 81 | 82 | // Scott, D. 1979. 83 | // On optimal and data-based histograms. 84 | // Biometrika, 66:605-610. 85 | const float dx = 86 | 3.49f * stdev * std::pow(static_cast(data.rows()), -0.33f); 87 | 88 | // if calculated dx is too small then set number of bins to pre-determined 89 | // number 90 | if (dx > m_span.delta()[0] / 200.f) { 91 | m_number_of_bins = static_cast(std::round(m_span.delta()[0] / dx)); 92 | } else { 93 | m_number_of_bins = 200; 94 | } 95 | } 96 | 97 | const float dx = m_span.delta()[0] / m_number_of_bins; 98 | 99 | std::vector bin_y(m_number_of_bins); 100 | 101 | // zero y bin values 102 | std::fill(bin_y.begin(), bin_y.end(), 0.f); 103 | 104 | // accumulate data into histogram 105 | std::for_each(x_begin, x_end, [&](const float x) { 106 | const auto i = static_cast(std::floor((x - m_span.bmin[0]) / dx)); 107 | if (i >= 0 && i < m_number_of_bins) { 108 | ++(bin_y[i]); 109 | } 110 | }); 111 | 112 | // return new data set, making sure to set ymin to zero 113 | DataWithAesthetic ret; 114 | ret.x(m_span.bmin[0], m_span.bmax[0]).y(bin_y); 115 | ret.y(0.f, ret.limits().bmax[Aesthetic::y::index]); 116 | return ret; 117 | } 118 | 119 | } // namespace trase 120 | -------------------------------------------------------------------------------- /src/backend/Backend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "backend/Backend.hpp" 35 | 36 | #include 37 | #include 38 | 39 | namespace trase { 40 | 41 | FontManager::FontManager() { 42 | #ifdef _WIN32 43 | const char sep = '\\'; 44 | #else 45 | const char sep = '/'; 46 | #endif 47 | add_font_dir(std::string(TRASE_SOURCE_DIR) + sep + "font"); 48 | add_font_dir(std::string(TRASE_INSTALL_DIR) + sep + "font"); 49 | } 50 | 51 | void FontManager::clear_font_dirs() { 52 | m_font_dirs.clear(); 53 | m_list_of_available_fonts.clear(); 54 | } 55 | 56 | void FontManager::add_system_fonts() { 57 | #ifdef _WIN32 58 | const std::string system_font_dir = "c:\\Windows\\Fonts"; 59 | #elif __APPLE__ 60 | const std::string system_font_dir = "/Library/Fonts/"; 61 | #elif __linux__ 62 | const std::string system_font_dir = "/usr/share/fonts/"; 63 | #elif __unix__ // all unices not caught above 64 | const std::string system_font_dir = "/usr/share/fonts/"; 65 | #elif defined(_POSIX_VERSION) 66 | const std::string system_font_dir = "/usr/share/fonts/"; 67 | #else 68 | #error "Unknown system" 69 | #endif 70 | add_font_dir(system_font_dir); 71 | } 72 | 73 | void FontManager::add_font_dir(const std::string &path) { 74 | m_font_dirs.push_back(path); 75 | list_fonts(m_font_dirs.back()); 76 | } 77 | 78 | void FontManager::list_fonts(const std::string &path) { 79 | #ifdef _WIN32 80 | const char sep = '\\'; 81 | #else 82 | const char sep = '/'; 83 | #endif 84 | 85 | if (auto dir = opendir(path.c_str())) { 86 | while (auto f = readdir(dir)) { 87 | if (static_cast(f->d_name) == nullptr || f->d_name[0] == '.') { 88 | continue; 89 | } 90 | if (f->d_type == DT_DIR) { 91 | list_fonts(path + sep + static_cast(f->d_name)); 92 | } 93 | if (f->d_type == DT_REG && static_cast(f->d_name) != nullptr) { 94 | std::string name(static_cast(f->d_name)); 95 | std::string ext("ttf"); 96 | if (name.length() >= ext.length() && 97 | 0 == 98 | name.compare(name.length() - ext.length(), ext.length(), ext)) { 99 | m_list_of_available_fonts.push_back(path + sep + 100 | static_cast(f->d_name)); 101 | } 102 | } 103 | } 104 | closedir(dir); 105 | } 106 | } 107 | 108 | std::string FontManager::find_font(const std::string &name1, 109 | const std::string &name2) { 110 | auto it = std::find_if(m_list_of_available_fonts.begin(), 111 | m_list_of_available_fonts.end(), [&](std::string i) { 112 | if (i.find(name1) == std::string::npos) { 113 | return false; 114 | } 115 | if (name2.empty()) { 116 | return true; 117 | } 118 | std::string lower = i; 119 | std::transform( 120 | lower.begin(), lower.end(), lower.begin(), 121 | [](unsigned char c) { return std::tolower(c); }); 122 | return lower.find(name2) != std::string::npos; 123 | }); 124 | if (it == m_list_of_available_fonts.end()) { 125 | return ""; 126 | } 127 | return *it; 128 | } 129 | 130 | } // namespace trase 131 | -------------------------------------------------------------------------------- /tests/TestBBox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include 37 | 38 | #include "util/BBox.hpp" 39 | 40 | TEST_CASE("bbox constructors", "[bbox]") { 41 | 42 | using vec3int = trase::Vector; 43 | const int int_max = std::numeric_limits::max(); 44 | const int epsilon = std::numeric_limits::epsilon(); 45 | 46 | vec3int lower = {1, 2, 3}; 47 | vec3int upper = {11, 22, 33}; 48 | 49 | trase::bbox no_args{}; 50 | CHECK((no_args.bmin == vec3int::Constant(int_max)).all()); 51 | CHECK((no_args.bmax == vec3int::Constant(-int_max)).all()); 52 | 53 | trase::bbox one_arg{lower}; 54 | CHECK((one_arg.bmin == lower).all()); 55 | CHECK((one_arg.bmax == lower + vec3int::Constant(epsilon)).all()); 56 | 57 | trase::bbox two_args{lower, upper}; 58 | CHECK((two_args.bmin == lower).all()); 59 | CHECK((two_args.bmax == upper).all()); 60 | } 61 | 62 | TEST_CASE("bbox conversion to_coords", "[bbox]") { 63 | 64 | using vec2f = trase::Vector; 65 | const float epsilon = std::numeric_limits::epsilon(); 66 | 67 | vec2f pix_min = {10.f, 15.f}; 68 | vec2f pix_max = {75.f, 70.f}; 69 | trase::bbox pixels = {pix_min, pix_max}; 70 | 71 | vec2f lim_min = {0.f, 0.f}; 72 | vec2f lim_max = {1.f, 1.f}; 73 | trase::bbox limits = {lim_min, lim_max}; 74 | 75 | // points in the limits coordinate system 76 | vec2f p_lim_random = {.25f, .3f}; 77 | vec2f p_lim_bot_lt = {0.f, 0.f}; 78 | vec2f p_lim_bot_rt = {1.f, 0.f}; 79 | vec2f p_lim_top_lt = {0.f, 1.f}; 80 | vec2f p_lim_top_rt = {1.f, 1.f}; 81 | 82 | // corresponding points in the pixels coordinate system 83 | vec2f p_pix_random = {26.25f, 53.5f}; 84 | vec2f p_pix_bot_lt = {10.f, 70.f}; 85 | vec2f p_pix_bot_rt = {75.f, 70.f}; 86 | vec2f p_pix_top_lt = {10.f, 15.f}; 87 | vec2f p_pix_top_rt = {75.f, 15.f}; 88 | 89 | // Check transforms to pixels from limits 90 | CHECK(trase::approx_equal(limits.to_coords(pixels, p_lim_random), 91 | p_pix_random, epsilon) 92 | .all()); 93 | CHECK(trase::approx_equal(limits.to_coords(pixels, p_lim_bot_lt), 94 | p_pix_bot_lt, epsilon) 95 | .all()); 96 | CHECK(trase::approx_equal(limits.to_coords(pixels, p_lim_bot_rt), 97 | p_pix_bot_rt, epsilon) 98 | .all()); 99 | CHECK(trase::approx_equal(limits.to_coords(pixels, p_lim_top_lt), 100 | p_pix_top_lt, epsilon) 101 | .all()); 102 | CHECK(trase::approx_equal(limits.to_coords(pixels, p_lim_top_rt), 103 | p_pix_top_rt, epsilon) 104 | .all()); 105 | 106 | // Check transforms to limits from pixels 107 | CHECK(trase::approx_equal(pixels.to_coords(limits, p_pix_random), 108 | p_lim_random, epsilon) 109 | .all()); 110 | CHECK(trase::approx_equal(pixels.to_coords(limits, p_pix_bot_lt), 111 | p_lim_bot_lt, epsilon) 112 | .all()); 113 | CHECK(trase::approx_equal(pixels.to_coords(limits, p_pix_bot_rt), 114 | p_lim_bot_rt, epsilon) 115 | .all()); 116 | CHECK(trase::approx_equal(pixels.to_coords(limits, p_pix_top_lt), 117 | p_lim_top_lt, epsilon) 118 | .all()); 119 | CHECK(trase::approx_equal(pixels.to_coords(limits, p_pix_top_rt), 120 | p_lim_top_rt, epsilon) 121 | .all()); 122 | } 123 | -------------------------------------------------------------------------------- /src/frontend/Figure.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | 37 | #include "frontend/Figure.hpp" 38 | 39 | #ifdef __EMSCRIPTEN__ 40 | #include 41 | #endif 42 | 43 | namespace trase { 44 | 45 | template 46 | void Figure::draw(AnimatedBackend &backend) { 47 | auto name = "Figure " + std::to_string(m_id); 48 | backend.init(m_pixels.bmax, name.c_str(), m_time_span); 49 | for (const auto &i : m_children) { 50 | i->dispatch(backend); 51 | } 52 | backend.finalise(); 53 | } 54 | 55 | template 56 | void Figure::render_interactive_frame(Backend &backend) { 57 | const vfloat2_t win_limits = backend.begin_frame(); 58 | if ((win_limits != m_pixels.bmax).any()) { 59 | m_pixels.bmax = win_limits; 60 | for (const auto &i : m_children) { 61 | i->resize(m_pixels); 62 | } 63 | } 64 | 65 | if (backend.mouse_dragging()) { 66 | vfloat2_t delta = backend.mouse_drag_delta(); 67 | for (const auto &drawable : m_children) { 68 | auto axis = std::dynamic_pointer_cast(drawable); 69 | // scale by axis pixel area 70 | vfloat2_t ax_delta = delta / (axis->pixels().bmax * vfloat2_t(-1, 1)); 71 | 72 | // scale by axis limits 73 | ax_delta[0] *= axis->limits().bmax[Aesthetic::x::index] - 74 | axis->limits().bmin[Aesthetic::x::index]; 75 | ax_delta[1] *= axis->limits().bmax[Aesthetic::y::index] - 76 | axis->limits().bmin[Aesthetic::y::index]; 77 | 78 | axis->limits().bmin[Aesthetic::x::index] += ax_delta[0]; 79 | axis->limits().bmax[Aesthetic::x::index] += ax_delta[0]; 80 | axis->limits().bmin[Aesthetic::y::index] += ax_delta[1]; 81 | axis->limits().bmax[Aesthetic::y::index] += ax_delta[1]; 82 | } 83 | backend.mouse_drag_reset_delta(); 84 | } 85 | 86 | const float time = backend.get_time(); 87 | const float looped_time = std::fmod(time, m_time_span); 88 | 89 | for (const auto &i : m_children) { 90 | i->dispatch(backend, looped_time); 91 | } 92 | 93 | backend.end_frame(); 94 | } 95 | 96 | #ifdef __EMSCRIPTEN__ 97 | template void Figure::emscripten_callback(void *data) { 98 | using data_t = std::pair
; 99 | auto self = static_cast(data)->first; 100 | auto backend = static_cast(data)->second; 101 | self->render_interactive_frame(*backend); 102 | } 103 | #endif 104 | 105 | template void Figure::show(Backend &backend) { 106 | auto name = "Figure " + std::to_string(m_id); 107 | backend.init(this->m_pixels.bmax, name.c_str()); 108 | 109 | if (!backend.is_interactive()) { 110 | throw Exception("Figure::show() should only be called with interactive " 111 | "backends. Use Figure::draw() instead"); 112 | } 113 | 114 | // Main loop 115 | #ifdef __EMSCRIPTEN__ 116 | auto data = std::make_pair(this, &backend); 117 | emscripten_set_main_loop_arg( 118 | (em_arg_callback_func)&emscripten_callback, &data, 0, 1); 119 | #else 120 | while (!backend.should_close()) { 121 | render_interactive_frame(backend); 122 | } 123 | #endif 124 | backend.finalise(); 125 | } 126 | 127 | template 128 | void Figure::draw(Backend &backend, const float time) { 129 | auto name = "Figure " + std::to_string(m_id); 130 | backend.init(m_pixels.bmax, name.c_str()); 131 | for (const auto &i : m_children) { 132 | i->dispatch(backend, time); 133 | } 134 | backend.finalise(); 135 | } 136 | 137 | } // namespace trase 138 | -------------------------------------------------------------------------------- /src/util/CSVDownloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "CSVDownloader.hpp" 35 | #include "util/Exception.hpp" 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | namespace trase { 47 | template 48 | void split(const std::string &s, char delim, Out result) { 49 | std::stringstream ss(s); 50 | std::string item; 51 | while (std::getline(ss, item, delim)) { 52 | if (!item.empty()) { 53 | *(result++) = item; 54 | } 55 | } 56 | } 57 | size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { 58 | std::string string_data((const char *)ptr, (size_t)size * nmemb); 59 | *((std::stringstream *)stream) << string_data; 60 | return size * nmemb; 61 | } 62 | 63 | CSVDownloader::CSVDownloader() : m_delim(',') { 64 | m_curl = curl_easy_init(); 65 | } 66 | 67 | CSVDownloader::~CSVDownloader() { 68 | curl_easy_cleanup(m_curl); 69 | } 70 | 71 | CSVDownloader::data_t 72 | CSVDownloader::parse_csv(std::stringstream &out, 73 | const std::vector &labels_in) { 74 | CSVDownloader::data_t store; 75 | // parse the stringstream as a csv with given delimiter 76 | std::string line; 77 | std::vector labels; 78 | 79 | // if input labels is empty, assume 1st line of data are labels 80 | if (labels_in.empty()) { 81 | std::getline(out, line); 82 | split(line, m_delim, std::back_inserter(labels)); 83 | } else { 84 | labels.resize(labels_in.size()); 85 | std::copy(labels_in.begin(), labels_in.end(), labels.begin()); 86 | } 87 | 88 | // parse data 89 | while (std::getline(out, line)) { 90 | // ignore all whitespace lines 91 | if (std::all_of(line.begin(), line.end(), 92 | [](unsigned char c) { return std::isspace(c); })) { 93 | continue; 94 | } 95 | 96 | // split up line according to delimiter 97 | std::vector elems; 98 | split(line, m_delim, std::back_inserter(elems)); 99 | if (elems.size() != labels.size()) { 100 | throw Exception("CSVDownloader found differing line lengths"); 101 | } 102 | 103 | // store individual elements from this line 104 | for (size_t i = 0; i < labels.size(); ++i) { 105 | store[labels[i]].push_back(elems[i]); 106 | } 107 | } 108 | return store; 109 | } 110 | 111 | CSVDownloader::data_t 112 | CSVDownloader::download(const std::string &url, 113 | const std::vector &labels) { 114 | // use curl to read url to a stringstream 115 | curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); 116 | /* Do not check certificate*/ 117 | curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L); 118 | /* tell libcurl to follow redirection */ 119 | curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L); 120 | curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 121 | 1); // Prevent "longjmp causes uninitialized stack frame" bug 122 | curl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, "deflate"); 123 | curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data); 124 | std::stringstream out; 125 | curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &out); 126 | /* Perform the request, res will get the return code */ 127 | CURLcode res = curl_easy_perform(m_curl); 128 | /* Check for errors */ 129 | if (res != CURLE_OK) { 130 | fprintf(stderr, "curl_easy_perform() failed: %s\n", 131 | curl_easy_strerror(res)); 132 | } 133 | 134 | return parse_csv(out, labels); 135 | } 136 | 137 | } // namespace trase 138 | -------------------------------------------------------------------------------- /third-party/nanovg/nanovg_gl_utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2009-2013 Mikko Mononen memon@inside.org 3 | // 4 | // This software is provided 'as-is', without any express or implied 5 | // warranty. In no event will the authors be held liable for any damages 6 | // arising from the use of this software. 7 | // Permission is granted to anyone to use this software for any purpose, 8 | // including commercial applications, and to alter it and redistribute it 9 | // freely, subject to the following restrictions: 10 | // 1. The origin of this software must not be misrepresented; you must not 11 | // claim that you wrote the original software. If you use this software 12 | // in a product, an acknowledgment in the product documentation would be 13 | // appreciated but is not required. 14 | // 2. Altered source versions must be plainly marked as such, and must not be 15 | // misrepresented as being the original software. 16 | // 3. This notice may not be removed or altered from any source distribution. 17 | // 18 | #ifndef NANOVG_GL_UTILS_H 19 | #define NANOVG_GL_UTILS_H 20 | 21 | struct NVGLUframebuffer { 22 | NVGcontext* ctx; 23 | GLuint fbo; 24 | GLuint rbo; 25 | GLuint texture; 26 | int image; 27 | }; 28 | typedef struct NVGLUframebuffer NVGLUframebuffer; 29 | 30 | // Helper function to create GL frame buffer to render to. 31 | void nvgluBindFramebuffer(NVGLUframebuffer* fb); 32 | NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags); 33 | void nvgluDeleteFramebuffer(NVGLUframebuffer* fb); 34 | 35 | #endif // NANOVG_GL_UTILS_H 36 | 37 | #ifdef NANOVG_GL_IMPLEMENTATION 38 | 39 | #if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3) 40 | // FBO is core in OpenGL 3>. 41 | # define NANOVG_FBO_VALID 1 42 | #elif defined(NANOVG_GL2) 43 | // On OS X including glext defines FBO on GL2 too. 44 | # ifdef __APPLE__ 45 | # include 46 | # define NANOVG_FBO_VALID 1 47 | # endif 48 | #endif 49 | 50 | static GLint defaultFBO = -1; 51 | 52 | NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) 53 | { 54 | #ifdef NANOVG_FBO_VALID 55 | GLint defaultFBO; 56 | GLint defaultRBO; 57 | NVGLUframebuffer* fb = NULL; 58 | 59 | glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 60 | glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO); 61 | 62 | fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer)); 63 | if (fb == NULL) goto error; 64 | memset(fb, 0, sizeof(NVGLUframebuffer)); 65 | 66 | fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL); 67 | 68 | #if defined NANOVG_GL2 69 | fb->texture = nvglImageHandleGL2(ctx, fb->image); 70 | #elif defined NANOVG_GL3 71 | fb->texture = nvglImageHandleGL3(ctx, fb->image); 72 | #elif defined NANOVG_GLES2 73 | fb->texture = nvglImageHandleGLES2(ctx, fb->image); 74 | #elif defined NANOVG_GLES3 75 | fb->texture = nvglImageHandleGLES3(ctx, fb->image); 76 | #endif 77 | 78 | fb->ctx = ctx; 79 | 80 | // frame buffer object 81 | glGenFramebuffers(1, &fb->fbo); 82 | glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); 83 | 84 | // render buffer object 85 | glGenRenderbuffers(1, &fb->rbo); 86 | glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo); 87 | glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h); 88 | 89 | // combine all 90 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 91 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 92 | 93 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 94 | #ifdef GL_DEPTH24_STENCIL8 95 | // If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback. 96 | // Some graphics cards require a depth buffer along with a stencil. 97 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); 98 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 99 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 100 | 101 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 102 | #endif // GL_DEPTH24_STENCIL8 103 | goto error; 104 | } 105 | 106 | glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 107 | glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 108 | return fb; 109 | error: 110 | glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 111 | glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 112 | nvgluDeleteFramebuffer(fb); 113 | return NULL; 114 | #else 115 | NVG_NOTUSED(ctx); 116 | NVG_NOTUSED(w); 117 | NVG_NOTUSED(h); 118 | NVG_NOTUSED(imageFlags); 119 | return NULL; 120 | #endif 121 | } 122 | 123 | void nvgluBindFramebuffer(NVGLUframebuffer* fb) 124 | { 125 | #ifdef NANOVG_FBO_VALID 126 | if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 127 | glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO); 128 | #else 129 | NVG_NOTUSED(fb); 130 | #endif 131 | } 132 | 133 | void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) 134 | { 135 | #ifdef NANOVG_FBO_VALID 136 | if (fb == NULL) return; 137 | if (fb->fbo != 0) 138 | glDeleteFramebuffers(1, &fb->fbo); 139 | if (fb->rbo != 0) 140 | glDeleteRenderbuffers(1, &fb->rbo); 141 | if (fb->image >= 0) 142 | nvgDeleteImage(fb->ctx, fb->image); 143 | fb->ctx = NULL; 144 | fb->fbo = 0; 145 | fb->rbo = 0; 146 | fb->texture = 0; 147 | fb->image = -1; 148 | free(fb); 149 | #else 150 | NVG_NOTUSED(fb); 151 | #endif 152 | } 153 | 154 | #endif // NANOVG_GL_IMPLEMENTATION 155 | -------------------------------------------------------------------------------- /src/frontend/Figure.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /// \file Figure.hpp 35 | 36 | #ifndef FIGURE_H_ 37 | #define FIGURE_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "frontend/Axis.hpp" 44 | #include "frontend/Drawable.hpp" 45 | 46 | namespace trase { 47 | 48 | /// The primary Drawable for each figure 49 | /// 50 | /// Each Figure points to one or more Axis objects that are drawn within the 51 | /// Figure. 52 | class Figure : public Drawable { 53 | /// a unique id for this figure 54 | int m_id; 55 | 56 | /// number of axis subplots in each direction 57 | vint2_t m_axis_layout; 58 | 59 | /// axis subplots 60 | std::unordered_map, vint2_hash, vint2_equal> 61 | m_axis_subplots; 62 | 63 | /// total number of figures currentl created 64 | static int m_num_windows; 65 | 66 | public: 67 | /// create a new figure with the given number of pixels 68 | /// 69 | /// \param pixels the number of pixels along the {width, height} of the figure 70 | explicit Figure(const std::array &pixels); 71 | 72 | virtual ~Figure() = default; 73 | 74 | TRASE_DISPATCH_BACKENDS 75 | 76 | /// Create a new axis at position (0,0) and return a shared pointer to it 77 | /// If the axis already exists returns a pointer to the existing axis 78 | /// \return a shared pointer to the new axis 79 | std::shared_ptr axis(); 80 | 81 | /// Create a new axis at position (\p i, \p j) and return a shared pointer to 82 | /// it If the axis already exists returns a pointer to the existing axis 83 | /// \return a shared pointer to the new axis 84 | std::shared_ptr axis(int i, int j); 85 | 86 | /// Draw the Figure using the Backend provided 87 | /// 88 | /// This function takes control of the render loop and animates the 89 | /// Figure until the window is closed. 90 | /// 91 | /// TODO: issue #86 - only works for the BackendGL backend 92 | /// 93 | /// \param backend the Backend used to draw the figure. 94 | template void show(Backend &backend); 95 | 96 | /// Draw the Figure using the AnimatedBackend provided 97 | /// 98 | /// \param backend the AnimatedBackend used to draw the figure. 99 | template void draw(AnimatedBackend &backend); 100 | 101 | /// Draw the Figure at a given time using the Backend provided 102 | /// 103 | /// \param backend the Backend used to draw the figure. 104 | /// \param time the Figure is drawn at this time 105 | template void draw(Backend &backend, float time); 106 | 107 | private: 108 | /// creates a new Axis at position \p new_position of the subplot array, or 109 | /// returns existing Axis if one exists at this position. If \p new_position 110 | /// is larger than the maximum extent of the current subplot array (see 111 | /// m_axis_layout), then the subplot array is extended to cover the new 112 | /// position, and all existing Axis children are resized accordingly 113 | std::shared_ptr update_layout(const vint2_t &new_position); 114 | 115 | template void render_interactive_frame(Backend &backend); 116 | #ifdef __EMSCRIPTEN__ 117 | template static void emscripten_callback(void *data); 118 | #endif 119 | }; 120 | 121 | /// create a new Figure 122 | /// 123 | /// \param pixels (optional) the number of pixels along the {width, height} of 124 | /// the figure 125 | inline std::shared_ptr
figure(std::array pixels = { 126 | {800.0, 600.0}}) { 127 | return std::make_shared
(pixels); 128 | } 129 | 130 | } // namespace trase 131 | 132 | #include "frontend/Figure.tcc" 133 | 134 | #endif // FIGURE_H_ 135 | -------------------------------------------------------------------------------- /tests/TestAxis.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "catch.hpp" 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include "DummyDraw.hpp" 41 | #include "trase.hpp" 42 | 43 | using namespace trase; 44 | 45 | TEST_CASE("axis can be created", "[axis]") { 46 | auto fig = figure({800, 600}); 47 | auto ax = fig->axis(); 48 | } 49 | 50 | TEST_CASE("check plot methods can be invoked", "[axis]") { 51 | 52 | std::vector three_ints_a = {1, 2, 3}; 53 | std::vector three_ints_b = {1, 2, 3}; 54 | std::vector four_ints = {1, 2, 3, 4}; 55 | 56 | auto fig = figure(); 57 | auto ax = fig->axis(); 58 | 59 | CHECK_NOTHROW(ax->line(create_data().x(three_ints_a).y(three_ints_b))); 60 | CHECK_NOTHROW(ax->line(create_data().x(three_ints_a).y(three_ints_b))); 61 | CHECK_NOTHROW(ax->plot(0)); 62 | CHECK_NOTHROW(ax->plot(1)); 63 | 64 | CHECK_THROWS_AS(ax->plot(2), std::out_of_range); 65 | CHECK_THROWS_AS(ax->plot(-1), std::out_of_range); 66 | 67 | CHECK_THROWS_AS(ax->line(create_data().x(three_ints_a).y(four_ints)), 68 | Exception); 69 | } 70 | 71 | TEST_CASE("check limit setting", "[axis]") { 72 | auto fig = figure(); 73 | auto ax = fig->axis(); 74 | CHECK(ax->limits().is_empty() == true); 75 | ax->xlim({0.0f, 1.0f}); 76 | CHECK(ax->limits().bmin[0] == 0.0f); 77 | CHECK(ax->limits().bmax[0] == 1.0f); 78 | ax->ylim({-1.0f, 1.0f}); 79 | CHECK(ax->limits().bmin[1] == -1.0f); 80 | CHECK(ax->limits().bmax[1] == 1.0f); 81 | } 82 | 83 | TEST_CASE("to/from pixel coordinates", "[axis]") { 84 | // axis will be 80 x 80 pixels from 10 - 90 each dim 85 | auto fig = figure({100, 100}); 86 | auto ax = fig->axis(); 87 | CHECK(ax->pixels().bmin[0] == 10.f); 88 | CHECK(ax->pixels().bmin[1] == 10.f); 89 | CHECK(ax->pixels().bmax[0] == 90.f); 90 | CHECK(ax->pixels().bmax[1] == 90.f); 91 | ax->xlim({0.0f, 1.0f}); 92 | ax->ylim({0.0f, 1.0f}); 93 | auto middle1 = vfloat2_t{ax->to_display(0.5f), 94 | ax->to_display(0.5f)}; 95 | CHECK(middle1[0] == 50.f); 96 | CHECK(middle1[1] == 50.f); 97 | auto middle2 = vfloat2_t{ax->from_display(middle1[0]), 98 | ax->from_display(middle1[1])}; 99 | CHECK(middle2[0] == 0.5f); 100 | CHECK(middle2[1] == 0.5f); 101 | } 102 | 103 | TEST_CASE("labels", "[axis]") { 104 | // axis will be 80 x 80 pixels from 10 - 90 each dim 105 | auto fig = figure(); 106 | auto ax = fig->axis(); 107 | const std::vector x = {1.f, 2.f, 3.f}; 108 | const std::vector y = {1.f, 2.f, 3.f}; 109 | auto data = create_data().x(x).y(y); 110 | auto plot1 = ax->line(data); 111 | plot1->set_label("plot1"); 112 | CHECK(plot1->get_label() == "plot1"); 113 | auto plot2 = ax->line(data); 114 | plot2->set_label("plot2"); 115 | CHECK(plot1->get_label() == "plot1"); 116 | CHECK(plot2->get_label() == "plot2"); 117 | auto plot3 = ax->line(data); 118 | CHECK(plot3->get_label() == ""); 119 | } 120 | 121 | TEST_CASE("set number of ticks", "[axis]") { 122 | auto fig = figure(); 123 | auto ax = fig->axis(); 124 | const std::vector x = {1.f, 2.f, 3.f}; 125 | const std::vector y = {1.f, 2.f, 3.f}; 126 | auto data = create_data().x(x).y(y); 127 | auto line = ax->line(data); 128 | CHECK(ax->get_ticks()[0] == 0); 129 | CHECK(ax->get_ticks()[1] == 0); 130 | DummyDraw::draw("axis", fig); 131 | ax->set_ticks({10, 0}); 132 | DummyDraw::draw("axis", fig); 133 | CHECK(ax->get_ticks()[0] == 10); 134 | CHECK(ax->get_ticks()[1] == 0); 135 | ax->set_ticks({10, 10}); 136 | DummyDraw::draw("axis", fig); 137 | CHECK(ax->get_ticks()[0] == 10); 138 | CHECK(ax->get_ticks()[1] == 10); 139 | } 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # trase 2 | 3 | [![Ubuntu unit](https://github.com/trase-cpp/trase/workflows/Ubuntu%20unit/badge.svg)](https://github.com/trase-cpp/trase/actions) 4 | [![macOS unit](https://github.com/trase-cpp/trase/workflows/macOS%20unit/badge.svg)](https://github.com/trase-cpp/trase/actions) 5 | [![Windows unit](https://github.com/trase-cpp/trase/workflows/Windows%20unit/badge.svg)](https://github.com/trase-cpp/trase/actions) 6 | 7 | [![codecov](https://codecov.io/gh/trase-cpp/trase/branch/master/graph/badge.svg)](https://codecov.io/gh/trase-cpp/trase) 8 | [![BCH compliance](https://bettercodehub.com/edge/badge/trase-cpp/trase?branch=master)](https://bettercodehub.com/) 9 | [![codedocs.xyz](https://codedocs.xyz/trase-cpp/trase.svg)](https://codedocs.xyz/trase-cpp/trase/) 10 | 11 | Trase is a lightweight scientific plotting library for C++ with animation 12 | support. It enables you to construct plots and write them out to animated svg 13 | files, or display them in an OpenGL window. The main library and svg backend 14 | have no dependencies other than the standard library. The OpenGL backend 15 | requires [GLFW](http://www.glfw.org/). 16 | 17 |

18 | 20 |

21 | 22 | 23 | For example, the above svg image was generated with the following code. 24 | 25 | ```cpp 26 | auto fig = figure(); 27 | auto ax = fig->axis(); 28 | const int n = 100; 29 | const int nframes = 10; 30 | std::vector x(n); 31 | std::vector y(n); 32 | 33 | // define x points 34 | for (int i = 0; i < n; ++i) { 35 | x[i] = static_cast(i) / n; 36 | } 37 | 38 | // define y = sin(x) with given amplitude and frequency 39 | auto get_ysinx = [&](const float amplitude, const float freq) { 40 | for (int i = 0; i < n; ++i) { 41 | y[i] = amplitude * std::sin(6.28f * freq * x[i]); 42 | } 43 | return create_data().x(x).y(y); 44 | }; 45 | 46 | // create a static sin(x) function 47 | auto static_plot = ax->line(get_ysinx(1.f, 2.f)); 48 | static_plot->set_label("static"); 49 | 50 | // create a moving sin(x) function with varying amplitude 51 | auto moving_plot = ax->line(get_ysinx(1.f, 5.f)); 52 | moving_plot->set_label("moving"); 53 | 54 | for (int i = 1; i <= nframes; ++i) { 55 | const float nf = static_cast(nframes); 56 | const float amplitude = 1.f - 0.5f * std::sin(6.28f * i / nf); 57 | moving_plot->add_frame(get_ysinx(amplitude, 5.f), 3.f * i / nf); 58 | } 59 | 60 | // set label axes 61 | ax->xlabel("x"); 62 | ax->ylabel("y"); 63 | ax->title("the svg test"); 64 | ax->legend(); 65 | 66 | // output to svg 67 | std::ofstream out; 68 | out.open("readme.svg"); 69 | BackendSVG backend(out); 70 | fig->draw(backend); 71 | out.close(); 72 | ``` 73 | 74 | ## Contributing to Trase 75 | 76 | We welcome community pull requests for Trase, please see the guidelines 77 | [here](CONTRIBUTING.md). Potential areas for changes are: 78 | - Bug-fixes. Please add a relevant test in `tests/` demonstrating the fixed bug. 79 | - New geometry, aesthetic or transform. The design of Trase roughly follows the 80 | Grammer of Graphics, so looking at existing GOG packages such as 81 | [ggplot](https://ggplot2.tidyverse.org/reference) could give you some good 82 | ideas 83 | - New example showing how to use Trase. All the examples shown in the documentation 84 | are in `examples/`. 85 | - New drawing backend. There are two main types of backend. Classes derived from 86 | `Backend` are "pure" drawing classes in the same vein as 87 | [NanoVG](https://github.com/memononen/nanovg), while those derived from 88 | `AnimatedBackend` can also draw shapes or paths that have properties which 89 | animate over time. 90 | - Or consult the [issues](https://github.com/trase-cpp/trase/issues) for more 91 | ideas 92 | 93 | ## Usage 94 | 95 | 1. Clone this repository 96 | 97 | ```bash 98 | $ git clone https://github.com/martinjrobins/trase 99 | $ cd trase 100 | ``` 101 | 102 | 2. Build and install Trase. This uses an install dir of `$HOME/trase`, change 103 | this to wherever you like. This also builds the OpenGL backend of Trase 104 | (requires GLFW installed), switch this to `OFF` if you only want the svg 105 | backend. 106 | 107 | ```bash 108 | $ mkdir build 109 | $ cd build 110 | $ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/trase -Dtrase_BUILD_OPENGL=ON .. 111 | $ make install 112 | ``` 113 | 114 | 2. (alternate) If you are using the Xcode or Visual Studio generator, you need 115 | to specify the configuration in build time 116 | 117 | ```bash 118 | $ mkdir build 119 | $ cd build 120 | $ cmake -DCMAKE_INSTALL_PREFIX=$HOME/trase -Dtrase_BUILD_OPENGL=ON .. 121 | $ cmake --build . --target install --config Release 122 | ``` 123 | 124 | 3. In your C++ project, you might link against Trase with a `CMakeLists.txt` 125 | file like so: 126 | 127 | ```cmake 128 | cmake_minimum_required(VERSION 2.8.12) 129 | project(test) 130 | 131 | find_package(trase REQUIRED) 132 | 133 | add_executable(myexe test.cpp) 134 | target_link_libraries(myexe trase) 135 | ``` 136 | 137 | 4. When you build your project, you can tell CMake where you installed Trase 138 | using the `CMAKE_PREFIX_PATH` variable 139 | 140 | ```bash 141 | $ cmake -DCMAKE_PREFIX_PATH=$HOME/trase .. 142 | $ make 143 | ``` 144 | 145 | ## Acknowledgments 146 | 147 | Trase uses [NanoVG](https://github.com/memononen/nanovg) for the OpenGL 148 | backend. The [Dirent port](https://github.com/tronkko/dirent) for Windows is 149 | used for finding local font files. 150 | -------------------------------------------------------------------------------- /tests/TestFigure.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of the Oxford RSE C++ Template project. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | // This tells Catch to provide a main() - only do this in one cpp file 35 | #define CATCH_CONFIG_MAIN 36 | #include "catch.hpp" 37 | 38 | #include 39 | #include 40 | 41 | #include "DummyDraw.hpp" 42 | #include "trase.hpp" 43 | 44 | using namespace trase; 45 | 46 | TEST_CASE("check figure can be created", "[figure]") { 47 | Figure fig0({600, 300}); 48 | auto fig1 = figure(); 49 | auto fig2 = figure({800, 600}); 50 | } 51 | 52 | TEST_CASE("check show throws", "[figure]") { 53 | auto fig = figure(); 54 | std::ofstream out; 55 | out.open("test_show_exception_trase_invalid_svg.svg"); 56 | BackendSVG backend(out); 57 | REQUIRE_THROWS_WITH(fig->show(backend), Catch::Contains("Figure::show()")); 58 | } 59 | 60 | TEST_CASE("adding a single Axis object to Figure", "[figure]") { 61 | auto fig = figure(); 62 | 63 | auto ax = fig->axis(); 64 | const std::vector x = {1.f, 2.f, 3.f}; 65 | const std::vector y = {1.f, 2.f, 3.f}; 66 | auto data = create_data().x(x).y(y); 67 | auto line = ax->line(data); 68 | 69 | CHECK(fig->axis() == ax); 70 | CHECK(fig->axis(0, 0) == ax); 71 | DummyDraw::draw("figure", fig); 72 | 73 | CHECK_THROWS_AS(fig->axis(-1, 1), std::out_of_range); 74 | CHECK_THROWS_AS(fig->axis(1, -1), std::out_of_range); 75 | CHECK_THROWS_AS(fig->axis(-1, -1), std::out_of_range); 76 | } 77 | 78 | TEST_CASE("adding various Axis objects to Figure", "[figure]") { 79 | auto fig = figure(); 80 | 81 | auto ax = fig->axis(); 82 | const std::vector x = {1.f, 2.f, 3.f}; 83 | const std::vector y = {1.f, 2.f, 3.f}; 84 | auto data = create_data().x(x).y(y); 85 | auto line = ax->line(data); 86 | 87 | CHECK(fig->axis() == ax); 88 | CHECK(fig->axis(0, 0) == ax); 89 | 90 | auto ax2 = fig->axis(1, 1); 91 | CHECK(ax2 != ax); 92 | const std::vector y2 = {3.f, 2.f, 1.f}; 93 | auto data2 = create_data().x(x).y(y2); 94 | ax2->points(data2); 95 | DummyDraw::draw("figure", fig); 96 | 97 | auto ax3 = fig->axis(0, 1); 98 | CHECK(ax3 != ax); 99 | CHECK(ax3 != ax2); 100 | ax3->line(data2); 101 | DummyDraw::draw("figure", fig); 102 | 103 | auto ax4 = fig->axis(0, 5); 104 | CHECK(ax4 != ax); 105 | CHECK(ax4 != ax2); 106 | CHECK(ax4 != ax3); 107 | ax4->points(data); 108 | DummyDraw::draw("figure", fig); 109 | } 110 | 111 | TEST_CASE("readme", "[figure]") { 112 | auto fig = figure(); 113 | auto ax = fig->axis(); 114 | const int n = 100; 115 | const int nframes = 10; 116 | std::vector x(n); 117 | std::vector y(n); 118 | 119 | // define x points 120 | for (int i = 0; i < n; ++i) { 121 | x[i] = static_cast(i) / n; 122 | } 123 | 124 | // define y = sin(x) with given amplitude and frequency 125 | auto get_ysinx = [&](const float amplitude, const float freq) { 126 | for (int i = 0; i < n; ++i) { 127 | y[i] = amplitude * std::sin(6.28f * freq * x[i]); 128 | } 129 | return create_data().x(x).y(y); 130 | }; 131 | 132 | // create a static sin(x) function 133 | auto static_plot = ax->line(get_ysinx(1.f, 2.f)); 134 | static_plot->set_label("static"); 135 | 136 | // create a moving sin(x) function with varying amplitude 137 | auto moving_plot = ax->line(get_ysinx(1.f, 5.f)); 138 | moving_plot->set_label("moving"); 139 | 140 | for (int i = 1; i <= nframes; ++i) { 141 | const float nf = static_cast(nframes); 142 | const float amplitude = 1.f - 0.5f * std::sin(6.28f * i / nf); 143 | moving_plot->add_frame(get_ysinx(amplitude, 5.f), 3.f * i / nf); 144 | } 145 | 146 | // set label axes 147 | ax->xlabel("x"); 148 | ax->ylabel("y"); 149 | ax->title("the svg test"); 150 | ax->legend(); 151 | 152 | // output to svg 153 | std::ofstream out; 154 | out.open("readme.svg"); 155 | BackendSVG backend(out); 156 | fig->draw(backend); 157 | out.close(); 158 | } 159 | -------------------------------------------------------------------------------- /src/frontend/Histogram.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018, University of Oxford. 3 | All rights reserved. 4 | 5 | University of Oxford means the Chancellor, Masters and Scholars of the 6 | University of Oxford, having an administrative office at Wellington 7 | Square, Oxford OX1 2JD, UK. 8 | 9 | This file is part of trase. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "frontend/Axis.hpp" 35 | #include "frontend/Histogram.hpp" 36 | 37 | namespace trase { 38 | 39 | template 40 | void Histogram::draw(AnimatedBackend &backend) { 41 | draw_frames(backend); 42 | } 43 | 44 | template 45 | void Histogram::draw(Backend &backend, const float time) { 46 | update_frame_info(time); 47 | draw_plot(backend); 48 | } 49 | 50 | template 51 | void Histogram::draw_legend(AnimatedBackend &backend, const bfloat2_t &box) { 52 | backend.stroke_color(m_style.color()); 53 | backend.stroke_width(m_style.line_width()); 54 | backend.fill_color(m_style.color()); 55 | backend.rect(box * vfloat2_t{0.75f, 0.75f}); 56 | } 57 | 58 | template 59 | void Histogram::draw_legend(Backend &backend, const float time, 60 | const bfloat2_t &box) { 61 | draw_legend(backend, box); 62 | } 63 | 64 | template 65 | void Histogram::draw_frames(AnimatedBackend &backend) { 66 | 67 | backend.stroke_color(m_style.color()); 68 | backend.stroke_width(m_style.line_width()); 69 | backend.fill_color(m_style.color()); 70 | 71 | // x should be constant and regular spaced with a dx calculated by the limits 72 | // and the number of rows 73 | const float x0 = m_data[0].limits().bmin[Aesthetic::x::index]; 74 | const float dx = 75 | (m_data[0].limits().bmax[Aesthetic::x::index] - x0) / m_data[0].rows(); 76 | 77 | for (int i = 0; i < m_data[0].rows(); ++i) { 78 | for (size_t f = 0; f < m_times.size(); ++f) { 79 | auto y_data = m_data[f].begin()[i]; 80 | auto y_min = m_axis->to_display(y_data); 81 | auto y_max = m_axis->to_display(0.f); 82 | auto x_min = m_axis->to_display(i * dx + x0); 83 | auto x_max = m_axis->to_display((i + 1.f) * dx + x0); 84 | backend.add_animated_rect(bfloat2_t({x_min, y_min}, {x_max, y_max}), 85 | m_times[f]); 86 | } 87 | backend.end_animated_rect(); 88 | } 89 | } 90 | 91 | template void Histogram::draw_plot(Backend &backend) { 92 | 93 | const int f = m_frame_info.frame_above; 94 | const float w1 = m_frame_info.w1; 95 | const float w2 = m_frame_info.w2; 96 | 97 | backend.stroke_color(m_style.color()); 98 | backend.stroke_width(m_style.line_width()); 99 | backend.fill_color(m_style.color()); 100 | 101 | // x should be constant and regular spaced with a dx calculated by the limits 102 | // and the number of rows 103 | const float x0 = m_data[0].limits().bmin[Aesthetic::x::index]; 104 | const float dx = 105 | (m_data[0].limits().bmax[Aesthetic::x::index] - x0) / m_data[0].rows(); 106 | 107 | if (w2 == 0.0f) { 108 | // exactly on a single frame 109 | auto y_data = m_data[f].begin(); 110 | for (int i = 0; i < m_data[0].rows(); ++i) { 111 | auto x_min = m_axis->to_display(i * dx + x0); 112 | auto x_max = m_axis->to_display((i + 1.f) * dx + x0); 113 | auto y_min = m_axis->to_display(y_data[i]); 114 | auto y_max = m_axis->to_display(0.f); 115 | backend.rect(bfloat2_t({x_min, y_min}, {x_max, y_max})); 116 | } 117 | } else { 118 | auto y0 = m_data[f - 1].begin(); 119 | auto y1 = m_data[f].begin(); 120 | for (int i = 0; i < m_data[0].rows(); ++i) { 121 | auto x_min = m_axis->to_display(i * dx + x0); 122 | auto x_max = m_axis->to_display((i + 1.f) * dx + x0); 123 | auto y_min = w1 * m_axis->to_display(y1[i]) + 124 | w2 * m_axis->to_display(y0[i]); 125 | auto y_max = m_axis->to_display(0.f); 126 | backend.rect(bfloat2_t({x_min, y_min}, {x_max, y_max})); 127 | } 128 | } 129 | } 130 | 131 | } // namespace trase 132 | --------------------------------------------------------------------------------