From 7b1094303d3548ed2989bfc3357f879471230445 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 08:59:55 +0200 Subject: [PATCH 1/7] add tests on macos --- .github/workflows/test_library.yaml | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/test_library.yaml b/.github/workflows/test_library.yaml index 9a8e496..4d64f2c 100644 --- a/.github/workflows/test_library.yaml +++ b/.github/workflows/test_library.yaml @@ -57,3 +57,42 @@ jobs: - name: Install run: | sudo cmake --workflow --preset workflow-release-install + + Tests-Viewshed-library-macos: + runs-on: macos-latest + + env: + QT_QPA_PLATFORM: "offscreen" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CMAKE_PREFIX_PATH: "/opt/homebrew/opt/qt@6" + + steps: + - name: Install dependencies + run: | + brew update + brew install ninja doxygen googletest gdal qt@6 + + - uses: actions/checkout@v6 + with: + repository: "JanCaha/cpp-simplerasters" + path: "cpp-simplerasters" + + - name: Install simplerasters + run: | + cd cpp-simplerasters + sudo cmake --workflow --preset workflow-release-install + cd .. + sudo rm -rf cpp-simplerasters + + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: true + + - name: Test + run: | + cmake --workflow --preset workflow-debug-tests + + - name: Install + run: | + sudo cmake --workflow --preset workflow-release-install From 3eb51d56b9b7c30c6b303798c35246245415d306 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 10:49:44 +0200 Subject: [PATCH 2/7] update location --- CMakePresets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakePresets.json b/CMakePresets.json index 00ffb25..7d7bb1b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -29,7 +29,7 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "BUILD_TESTS": "OFF", - "CMAKE_INSTALL_PREFIX": "/usr", + "CMAKE_INSTALL_PREFIX": "/usr/local", "BUILD_DOCUMENTATION": "ON" } } From 1089586ae6459958da21a1f5f92829baa19534d0 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 11:11:17 +0200 Subject: [PATCH 3/7] update scripts --- scripts/build_docker.sh | 29 ----------------------------- scripts/install.sh | 4 ++++ scripts/release.sh | 30 ------------------------------ scripts/release_to_ppa.sh | 20 -------------------- scripts/test.sh | 4 ++++ scripts/uninstall.sh | 10 +++++++--- 6 files changed, 15 insertions(+), 82 deletions(-) delete mode 100755 scripts/build_docker.sh delete mode 100755 scripts/release.sh delete mode 100755 scripts/release_to_ppa.sh diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh deleted file mode 100755 index 94cad64..0000000 --- a/scripts/build_docker.sh +++ /dev/null @@ -1,29 +0,0 @@ -set -u -set -e - -PWD=`pwd` - -cd docker - -IMAGE_NAME=viewshed - -DOCKER_IMAGE_NAME=cahik/viewshed:latest - -docker build -t $IMAGE_NAME . - -docker tag $IMAGE_NAME $DOCKER_IMAGE_NAME - -docker login --username cahik - -docker push $DOCKER_IMAGE_NAME - - -# DOCKER_IMAGE_NAME=cahik/viewshed:latest-python - -# docker build -t $IMAGE_NAME -f viewshed_install_from_ppa.dockerfile . - -# docker tag $IMAGE_NAME $DOCKER_IMAGE_NAME - -# docker login --username cahik - -# docker push $DOCKER_IMAGE_NAME \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index a73c2fd..f801340 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,2 +1,6 @@ +#!/bin/bash + +set -e + # install sudo cmake --workflow --preset workflow-release-install diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 27c25b1..0000000 --- a/scripts/release.sh +++ /dev/null @@ -1,30 +0,0 @@ -FOLDER=cpp-viewshed-library -PACKAGE=viewshed -VERSION=$(grep "project(" CMakeLists.txt | grep -E -o -e "[0-9\.]+" | head -n 1) -DEBIAN_VERSION=$(grep "viewshed (" debian/changelog | grep -E -o -e "[0-9\.-]+" | head -n 1) - -cmake \ - -S. \ - -B build \ - -G Ninja \ - -DCMAKE_CXX_COMPILER=clang++-13 \ - -D CMAKE_INSTALL_PREFIX=debian/tmp/ \ - -D CMAKE_BUILD_TYPE=Release \ - -D BUILD_TESTS:bool=off \ - -D CMAKE_INSTALL_PREFIX=/usr - -cmake --build build --config Release --target all -# cmake --build build --config Release --target install - -cd .. -dir -tar -acf "${PACKAGE}"_"${DEBIAN_VERSION}".orig.tar.gz $FOLDER -ls -l - -cd $FOLDER - -debuild -S -sa -d - -cd .. - -dput ppa:jancaha/gis-tools "${PACKAGE}"_"${DEBIAN_VERSION}"_source.changes \ No newline at end of file diff --git a/scripts/release_to_ppa.sh b/scripts/release_to_ppa.sh deleted file mode 100755 index a378b9e..0000000 --- a/scripts/release_to_ppa.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!bin/bash - -set -u -set -e - -PWD=`pwd` - -FOLDER=cpp-viewshed-library -PACKAGE=viewshed -VERSION=$(grep "project(" CMakeLists.txt | grep -E -o -e "[0-9\.]+" | head -n 1) -DEBIAN_VERSION=$(grep "viewshed (" debian/changelog | grep -E -o -e "[0-9\.-]+" | head -n 1) - -rm -rf build -cd .. -tar -acf "${PACKAGE}"_"${VERSION}".orig.tar.gz $FOLDER -cd $FOLDER -debuild -S -sa -d -cd .. -dput ppa:jancaha/gis-tools "${PACKAGE}"_"${DEBIAN_VERSION}"_source.changes -# rm $PACKAGE* \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh index 7e05e12..bd16fd3 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1 +1,5 @@ +#!/bin/bash + +set -e + cmake --workflow --preset workflow-debug-tests diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 6773ec1..20ac283 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -1,4 +1,8 @@ -sudo rm /usr/local/bin/inverseviewshed /usr/local/bin/viewshed /usr/local/bin/viewshedcalculator /usr/local/bin/losextractor -sudo rm /usr/local/lib/libviewshed.so /usr/local/lib/libviewshed.so.* /usr/local/lib/libviewshedwidgets.so /usr/local/lib/libviewshedwidgets.so.* +#!/bin/bash + +set -e + +sudo rm -f /usr/local/bin/inverseviewshed /usr/local/bin/viewshed /usr/local/bin/viewshedcalculator /usr/local/bin/losextractor +sudo rm -f /usr/local/lib/libviewshed.so /usr/local/lib/libviewshed.so.* /usr/local/lib/libviewshedwidgets.so /usr/local/lib/libviewshedwidgets.so.* sudo rm -rf /usr/local/include/Viewshed -sudo rm -rf /usr/local/lib/cmake/Viewshed \ No newline at end of file +sudo rm -rf /usr/local/lib/cmake/Viewshed From 72131d5b67baad6736a4f934a916e4dfad7649dd Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 11:23:10 +0200 Subject: [PATCH 4/7] rename --- .github/workflows/test_library.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/test_library.yaml b/.github/workflows/test_library.yaml index 4d64f2c..fae83f9 100644 --- a/.github/workflows/test_library.yaml +++ b/.github/workflows/test_library.yaml @@ -7,7 +7,7 @@ concurrency: on: [push, pull_request] jobs: - Tests-Viewshed-library: + Tests-Viewshed-library-linux: runs-on: ubuntu-26.04 env: @@ -33,8 +33,6 @@ jobs: - uses: actions/checkout@v6 with: - # Repository name with owner. For example, actions/checkout - # Default: ${{ github.repository }} repository: "JanCaha/cpp-simplerasters" path: "cpp-simplerasters" From dddb122e59eef94a7e869a31b53adc0bb3b7c86b Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 12:46:55 +0200 Subject: [PATCH 5/7] add tests --- tests/testcellevent.cpp | 83 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tests/testcellevent.cpp b/tests/testcellevent.cpp index ae2f05c..e2e39f9 100644 --- a/tests/testcellevent.cpp +++ b/tests/testcellevent.cpp @@ -112,6 +112,89 @@ TEST_F( CellEventTest, testCellEventCreation2 ) ASSERT_NEAR( c.mAngle, 3.926990, 0.000001 ); } +CellEvent makeEvent( CellEventPositionType type, int row, int col, double angle ) +{ + double elevs[3] = { 1000, 1000, 1000 }; + return CellEvent( type, row, col, 1.0, angle, elevs ); +} + +// operator< is used by std::sort in AbstractViewshed::sortEventList and must therefore +// be a strict weak ordering, otherwise the sort is undefined behaviour +// (it segfaults with libc++ on macOS) + +TEST( CellEventComparison, irreflexivity ) +{ + // a < a must always be false + CellEvent enter = makeEvent( CellEventPositionType::ENTER, 5, 5, 0.785398 ); + CellEvent center = makeEvent( CellEventPositionType::CENTER, 5, 5, 0.785398 ); + CellEvent exit = makeEvent( CellEventPositionType::EXIT, 5, 5, 0.785398 ); + + ASSERT_FALSE( enter < enter ); + ASSERT_FALSE( center < center ); + ASSERT_FALSE( exit < exit ); +} + +TEST( CellEventComparison, asymmetry ) +{ + // a < b and b < a must never both be true + // events of the same type with equal angles exist for cells on the same ray from the viewpoint + CellEvent exitA = makeEvent( CellEventPositionType::EXIT, 5, 5, 0.785398 ); + CellEvent exitB = makeEvent( CellEventPositionType::EXIT, 10, 10, 0.785398 ); + + ASSERT_FALSE( ( exitA < exitB ) && ( exitB < exitA ) ); + + CellEvent enterA = makeEvent( CellEventPositionType::ENTER, 5, 5, 0.785398 ); + CellEvent enterB = makeEvent( CellEventPositionType::ENTER, 10, 10, 0.785398 ); + + ASSERT_FALSE( ( enterA < enterB ) && ( enterB < enterA ) ); + + CellEvent centerA = makeEvent( CellEventPositionType::CENTER, 5, 5, 0.785398 ); + CellEvent centerB = makeEvent( CellEventPositionType::CENTER, 10, 10, 0.785398 ); + + ASSERT_FALSE( ( centerA < centerB ) && ( centerB < centerA ) ); +} + +TEST( CellEventComparison, behindTargetDuplicatesAreEquivalent ) +{ + // InverseViewshed creates at most one behind-target event per cell and type, + // so two events matching on row, col and type always share the same angle + // and neither may compare less than the other + CellEvent a = makeEvent( CellEventPositionType::EXIT, 5, 5, 0.785398 ); + a.mBehindTargetForInverseLoS = true; + + CellEvent b = makeEvent( CellEventPositionType::EXIT, 5, 5, 0.785398 ); + b.mBehindTargetForInverseLoS = true; + + ASSERT_FALSE( a < b ); + ASSERT_FALSE( b < a ); +} + +TEST( CellEventComparison, orderedByAngle ) +{ + CellEvent smallerAngle = makeEvent( CellEventPositionType::ENTER, 5, 5, 0.5 ); + CellEvent largerAngle = makeEvent( CellEventPositionType::EXIT, 10, 10, 1.5 ); + + ASSERT_TRUE( smallerAngle < largerAngle ); + ASSERT_FALSE( largerAngle < smallerAngle ); +} + +TEST( CellEventComparison, equalAngleOrderedByEventType ) +{ + // at equal angle the order is EXIT, CENTER, ENTER + CellEvent enter = makeEvent( CellEventPositionType::ENTER, 5, 5, 0.785398 ); + CellEvent center = makeEvent( CellEventPositionType::CENTER, 10, 10, 0.785398 ); + CellEvent exit = makeEvent( CellEventPositionType::EXIT, 15, 15, 0.785398 ); + + ASSERT_TRUE( exit < center ); + ASSERT_FALSE( center < exit ); + + ASSERT_TRUE( center < enter ); + ASSERT_FALSE( enter < center ); + + ASSERT_TRUE( exit < enter ); + ASSERT_FALSE( enter < exit ); +} + int main( int argc, char **argv ) { testing::InitGoogleTest( &argc, argv ); From cce768319a54fb5af28c3eb3bbd29af346a172fa Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Mon, 6 Jul 2026 12:55:30 +0200 Subject: [PATCH 6/7] fix cellsize operator< --- src/library/structures/cellevent.cpp | 41 +++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/library/structures/cellevent.cpp b/src/library/structures/cellevent.cpp index 36ba9b8..b62bdd8 100644 --- a/src/library/structures/cellevent.cpp +++ b/src/library/structures/cellevent.cpp @@ -34,32 +34,35 @@ bool CellEvent::operator==( const CellEvent &other ) const mBehindTargetForInverseLoS == other.mBehindTargetForInverseLoS; } -bool CellEvent::operator<( const CellEvent &other ) const +// order of events at equal angle: EXIT first, then CENTER, then ENTER +static int eventTypeSortRank( CellEventPositionType eventType ) { - - if ( mRow == other.mRow && mCol == other.mCol && mEventType == other.mEventType && mBehindTargetForInverseLoS && - other.mBehindTargetForInverseLoS ) - return false; - - if ( mAngle > other.mAngle ) + switch ( eventType ) { - return false; + case CellEventPositionType::EXIT: + return 0; + case CellEventPositionType::CENTER: + return 1; + default: + return 2; } - else if ( mAngle < other.mAngle ) +} + +// must be a strict weak ordering, otherwise std::sort is undefined behaviour +// (the previous version returned true for `a Date: Mon, 6 Jul 2026 13:10:52 +0200 Subject: [PATCH 7/7] bump version --- CMakeLists.txt | 2 +- README.md | 4 ++-- conda/meta.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29c0a6c..b10c606 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24.0) # Project Information -project(viewshed VERSION 6.0.0 DESCRIPTION "C++ Viewshed library based on GDAL and Qt" LANGUAGES CXX) +project(viewshed VERSION 6.1.0 DESCRIPTION "C++ Viewshed library based on GDAL and Qt" LANGUAGES CXX) # Library Name SET(LIBRARY_NAME "Viewshed") diff --git a/README.md b/README.md index 00a842f..e83779e 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,8 @@ If you use the library, please cite it accordingly: author = {Jan Caha}, title = {viewshed ({C++ Viewshed library based on GDAL and Qt})}, year = {2026} - date = {2026-07-05} - version = {6.0.0} + date = {2026-07-06} + version = {6.1.0} url = {https://github.com/JanCaha/cpp-viewshed-library}, } ``` diff --git a/conda/meta.yaml b/conda/meta.yaml index e5f022d..61b7b69 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -1,6 +1,6 @@ package: name: libviewshed - version: "6.0.0" + version: "6.1.0" source: path: ..