Skip to content

Commit f152c5f

Browse files
authored
Merge pull request #44 from JanCaha/development
version 4.0
2 parents 58d66ab + 7e6f22b commit f152c5f

14 files changed

+322
-7
lines changed

.github/workflows/create_releases.yaml

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ env:
1313
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1414
PACKAGE: viewshed
1515
COMPILER: c++
16+
PYTHON_VERSION: "3.10"
1617

1718
jobs:
1819

@@ -55,6 +56,8 @@ jobs:
5556

5657
- name: Install GDAL
5758
run: |
59+
sudo add-apt-repository ppa:ubuntugis/ppa
60+
sudo apt update
5861
sudo apt-get -y install gdal-bin libgdal-dev
5962
6063
- uses: robinraju/release-downloader@v1.8
@@ -89,7 +92,11 @@ jobs:
8992
run: |
9093
cmake --build build --config Release --target all
9194
cmake --build build --config Release --target pack_viewshed_library_deb
92-
95+
96+
- name: Install from DEB
97+
run: |
98+
sudo apt install ./_packages/viewshed_*.deb
99+
93100
- name: Upload DEB file as artifact
94101
uses: actions/upload-artifact@v3
95102
with:
@@ -112,7 +119,32 @@ jobs:
112119
github_token: ${{ secrets.GITHUB_TOKEN }}
113120
publish_dir: ./documentation
114121
publish_branch: gh-pages
115-
122+
123+
- uses: actions/setup-python@v4
124+
with:
125+
python-version: ${{env.PYTHON_VERSION}}
126+
architecture: 'x64'
127+
128+
- name: Install pip packages
129+
run: |
130+
pip install wheel py-build-cmake build
131+
132+
- uses: actions/checkout@v4
133+
with:
134+
repository: 'JanCaha/viewshed-library-pybind11'
135+
path: 'python-package'
136+
submodules: true
137+
138+
- name: Install package
139+
run: |
140+
cd python-package
141+
python -m build .
142+
143+
- uses: actions/upload-artifact@v3
144+
with:
145+
name: python-viewshed
146+
path: python-package/dist/viewshed*.whl
147+
116148
Release-Docker:
117149

118150
runs-on: ubuntu-latest
@@ -174,6 +206,15 @@ jobs:
174206
push: true
175207
tags: cahik/viewshed:latest
176208

209+
- name: Download artifact WHL
210+
uses: actions/download-artifact@v3
211+
with:
212+
name: python-viewshed
213+
214+
- name: Copy Python Viewshed to docker folder
215+
run: |
216+
mv viewshed-*.whl docker/install/
217+
177218
- name: Build and push Docker image version with Python
178219
uses: docker/build-push-action@v4
179220
with:

.github/workflows/test_library.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ jobs:
2626
2727
- name: Install GDAL
2828
run: |
29+
sudo add-apt-repository ppa:ubuntugis/ppa
30+
sudo apt update
2931
sudo apt-get -y install gdal-bin libgdal-dev
3032
3133
- uses: robinraju/release-downloader@v1.8

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.20.0)
22

3-
project(viewshed VERSION 3.0.0 DESCRIPTION "C++ Viewshed library based on GDAL and Qt" LANGUAGES CXX)
3+
project(viewshed VERSION 4.0.0 DESCRIPTION "C++ Viewshed library based on GDAL and Qt" LANGUAGES CXX)
44

55
SET(LIBRARY_NAME "viewshed")
66

debian/changelog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
viewshed (4.0.0-0) jammy; urgency=low
2+
3+
* add functions to calculate visibility raster (mask) as fast alternative
4+
5+
-- Jan Caha <jan.caha@outlook.com> Mon, 20 May 2024 11:21:29 +0200
6+
17
viewshed (3.0.0-0) jammy; urgency=low
28

39
* update to version 4.0.1 of BS::thread_pool

docker/viewshed_install_from_ppa.dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM ubuntu:jammy
22

33
RUN apt-get update && \
4-
apt-get -y -q install gpg wget lsb-core software-properties-common python3 python3-pip git cmake && \
4+
apt-get -y -q install gpg wget lsb-core software-properties-common python3 python3-pip && \
55
apt-get clean autoclean && \
66
apt-get autoremove --yes && \
77
rm -rf /var/lib/apt/lists/*
@@ -20,10 +20,10 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
2020
echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections && \
2121
add-apt-repository ppa:jancaha/gis-tools && \
2222
apt-get update && \
23-
apt-get -y -q install --no-install-recommends gdal-bin libgdal-dev qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools && \
2423
apt-get -y install simplerasters viewshed viewshed-bin && \
2524
apt-get clean autoclean && \
2625
apt-get autoremove --yes && \
2726
rm -rf /var/lib/apt/lists/*
2827

29-
RUN pip install git+https://github.com/JanCaha/viewshed-library-pybind11
28+
COPY install/ /
29+
RUN pip install viewshed-*.whl

include/viewshed/abstractviewshed.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,27 @@ namespace viewshed
291291
*/
292292
CellEvent cellEvent( size_t i ) { return mCellEvents.at( i ); }
293293

294+
/**
295+
* @brief Calculate visibility mask of areas which are visible from point (visibility), or from which the points
296+
* is visible (inverse visibility). The visibility raster is calculated using fast algorithm, significantly
297+
* faster than algorithms with visibility indices.
298+
*
299+
*/
300+
virtual void calculateVisibilityRaster() = 0;
301+
302+
/**
303+
* @brief Save visibility raster to file.
304+
*
305+
* @param filePath
306+
*/
307+
void saveVisibilityRaster( std::string filePath );
308+
309+
/**
310+
* @brief Calculate visibility mask raster.
311+
*
312+
*/
313+
void calculateVisibilityMask();
314+
294315
protected:
295316
/**
296317
* @brief LoSNodes in currently solved LoS while parsing event list.
@@ -374,6 +395,7 @@ namespace viewshed
374395
BS::thread_pool mThreadPool;
375396

376397
std::shared_ptr<ResultRasters> mResults = std::make_shared<ResultRasters>();
398+
std::shared_ptr<ProjectedSquareCellRaster> mVisibilityRaster = nullptr;
377399

378400
std::chrono::nanoseconds mTimeInit;
379401
std::chrono::nanoseconds mTimeSort;

include/viewshed/inverseviewshed.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ namespace viewshed
3737

3838
void addEventsFromCell( int &row, int &column, const double &pixelValue, bool &solveCell ) override;
3939

40+
void calculateVisibilityRaster() override;
41+
4042
private:
4143
double mObserverOffset;
4244
};

include/viewshed/viewshed.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ namespace viewshed
3535
void addEventsFromCell( int &row, int &column, const double &pixelValue, bool &solveCell ) override;
3636

3737
void submitToThreadpool( CellEvent &e ) override;
38+
39+
void calculateVisibilityRaster() override;
3840
};
3941

4042
} // namespace viewshed

src/library/visibility/abstractviewshed.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include "threadtasks.h"
33
#include "visibility.h"
44

5+
#include <map>
6+
57
using viewshed::AbstractViewshed;
68
using viewshed::LoSNode;
79

@@ -361,4 +363,8 @@ std::vector<LoSNode> AbstractViewshed::prepareLoSWithPoint( OGRPoint point )
361363
}
362364
}
363365
return losNodes;
364-
}
366+
}
367+
368+
void AbstractViewshed::saveVisibilityRaster( std::string filePath ) { mVisibilityRaster->saveFile( filePath ); };
369+
370+
void AbstractViewshed::calculateVisibilityMask() { mVisibilityMask = mVisibilityRaster; };

src/library/visibility/inverseviewshed.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,116 @@ void InverseViewshed::addEventsFromCell( int &row, int &column, const double &pi
191191
mCellEvents.push_back( mEventCenter );
192192
}
193193
}
194+
}
195+
196+
void InverseViewshed::calculateVisibilityRaster()
197+
{
198+
199+
mVisibilityRaster = std::make_shared<ProjectedSquareCellRaster>( *mInputDsm.get(), GDALDataType::GDT_Float32 );
200+
201+
std::chrono::_V2::steady_clock::time_point startTime = std::chrono::_V2::steady_clock::now();
202+
203+
std::map<double, LoSNode> los;
204+
205+
for ( LoSNode ln : mLosNodes )
206+
{
207+
if ( ln.mInverseLoSBehindTarget )
208+
{
209+
continue;
210+
}
211+
212+
los.insert( std::pair<double, LoSNode>( ln.centreDistance(), ln ) );
213+
}
214+
215+
std::size_t i = 0;
216+
for ( CellEvent e : mCellEvents )
217+
{
218+
// progressCallback( mCellEvents.size(), i );
219+
220+
switch ( e.mEventType )
221+
{
222+
case CellEventPositionType::ENTER:
223+
{
224+
if ( mPoint->mRow == e.mRow && mPoint->mCol == e.mCol )
225+
{
226+
break;
227+
}
228+
if ( e.mBehindTargetForInverseLoS )
229+
{
230+
break;
231+
}
232+
233+
mLoSNodeTemp = LoSNode( mPoint->mRow, mPoint->mCol, &e, mCellSize );
234+
los.insert( std::pair<double, LoSNode>( mLoSNodeTemp.centreDistance(), mLoSNodeTemp ) );
235+
break;
236+
}
237+
case CellEventPositionType::EXIT:
238+
{
239+
if ( mPoint->mRow == e.mRow && mPoint->mCol == e.mCol )
240+
{
241+
break;
242+
}
243+
if ( e.mBehindTargetForInverseLoS )
244+
{
245+
break;
246+
}
247+
248+
mLoSNodeTemp = LoSNode( mPoint->mRow, mPoint->mCol, &e, mCellSize );
249+
los.erase( mLoSNodeTemp.centreDistance() );
250+
break;
251+
}
252+
case CellEventPositionType::CENTER:
253+
{
254+
double maxGradient = -99;
255+
256+
mLoSNodeTemp = LoSNode( mPoint->mRow, mPoint->mCol, &e, mCellSize );
257+
double curCorr, gradient, elevation, horizontalAngle;
258+
259+
double visibilityElevation = mLoSNodeTemp.centreElevation() + mObserverOffset;
260+
261+
curCorr = Visibility::curvatureCorrections( mLoSNodeTemp.centreDistance(), mRefractionCoefficient,
262+
mEarthDiameter );
263+
elevation = visibilityElevation + curCorr;
264+
265+
gradient = Visibility::gradient( mPoint->totalElevation() - elevation, mLoSNodeTemp.centreDistance() );
266+
267+
double visibilityGradient = gradient;
268+
double visibilityDistance = mLoSNodeTemp.centreDistance();
269+
270+
for ( auto it = los.begin(); it != los.lower_bound( mLoSNodeTemp.centreDistance() ); ++it )
271+
{
272+
horizontalAngle = mLoSNodeTemp.centreAngle(); // + M_PI;
273+
274+
curCorr = Visibility::curvatureCorrections( visibilityDistance -
275+
it->second.distanceAtAngle( horizontalAngle ),
276+
mRefractionCoefficient, mEarthDiameter );
277+
278+
elevation = it->second.elevationAtAngle( horizontalAngle ) + curCorr;
279+
280+
gradient =
281+
Visibility::gradient( elevation - visibilityElevation,
282+
visibilityDistance - it->second.distanceAtAngle( horizontalAngle ) );
283+
284+
if ( gradient > maxGradient )
285+
{
286+
maxGradient = gradient;
287+
}
288+
}
289+
290+
double visible = 0;
291+
if ( maxGradient < visibilityGradient )
292+
{
293+
visible = 1;
294+
};
295+
mVisibilityRaster->writeValue( e.mRow, e.mCol, visible );
296+
297+
break;
298+
}
299+
}
300+
301+
i++;
302+
}
303+
304+
mTimeParse =
305+
std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::_V2::steady_clock::now() - startTime );
194306
}

0 commit comments

Comments
 (0)