Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions .github/workflows/test_library.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ concurrency:
on: [push, pull_request]

jobs:
Tests-Viewshed-library:
Tests-Viewshed-library-linux:
runs-on: ubuntu-26.04

env:
Expand All @@ -33,8 +33,45 @@ jobs:

- uses: actions/checkout@v6
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
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

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"

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
2 changes: 1 addition & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_TESTS": "OFF",
"CMAKE_INSTALL_PREFIX": "/usr",
"CMAKE_INSTALL_PREFIX": "/usr/local",
"BUILD_DOCUMENTATION": "ON"
}
}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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},
}
```
Expand Down
2 changes: 1 addition & 1 deletion conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package:
name: libviewshed
version: "6.0.0"
version: "6.1.0"

source:
path: ..
Expand Down
29 changes: 0 additions & 29 deletions scripts/build_docker.sh

This file was deleted.

4 changes: 4 additions & 0 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
#!/bin/bash

set -e

# install
sudo cmake --workflow --preset workflow-release-install
30 changes: 0 additions & 30 deletions scripts/release.sh

This file was deleted.

20 changes: 0 additions & 20 deletions scripts/release_to_ppa.sh

This file was deleted.

4 changes: 4 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#!/bin/bash

set -e

cmake --workflow --preset workflow-debug-tests
10 changes: 7 additions & 3 deletions scripts/uninstall.sh
Original file line number Diff line number Diff line change
@@ -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
sudo rm -rf /usr/local/lib/cmake/Viewshed
41 changes: 22 additions & 19 deletions src/library/structures/cellevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<a` on EXIT events with equal angles,
// which made std::sort in libc++ on macOS read out of bounds and segfault)
bool CellEvent::operator<( const CellEvent &other ) const
{
if ( mAngle < other.mAngle )
{
return true;
}
else

if ( other.mAngle < mAngle )
{
/*a.angle == b.angle */
if ( mEventType == CellEventPositionType::EXIT )
return true;
if ( other.mEventType == CellEventPositionType::EXIT )
return false;
if ( mEventType == CellEventPositionType::ENTER )
return false;
if ( other.mEventType == CellEventPositionType::ENTER )
return true;
return false;
}

/*a.angle == b.angle */
return eventTypeSortRank( mEventType ) < eventTypeSortRank( other.mEventType );
}
83 changes: 83 additions & 0 deletions tests/testcellevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
Loading