新增通视分析函数;新增第三方库地理距离计算库Erkir,利用该库封装了两个距离函数.
parent
cb3a310221
commit
fa6b6d00a4
Binary file not shown.
Binary file not shown.
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
#include "geospatialanalysis.h"
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
GeoSpatialAnalysis::GeoSpatialAnalysis()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@brief 两点间的可视性
|
||||||
|
* @param pntView 观察点
|
||||||
|
* @param pntObject 目标点
|
||||||
|
*/
|
||||||
|
UG3DAnalyst::SingleResult *GeoSpatialAnalysis::DoublePointVisibility(QMapControl* pMapControl,UGPoint2D pntView, UGPoint2D pntObject)
|
||||||
|
{
|
||||||
|
//通过下面的方法首先判断点所在的位置是否存在高程数据;
|
||||||
|
UGDatasetRasterPtr viewPtDataset = pMapControl->getDemDataSet(pntView);
|
||||||
|
UGDatasetRasterPtr objectPtDataset = pMapControl->getDemDataSet(pntObject);
|
||||||
|
|
||||||
|
if(viewPtDataset == NULL || objectPtDataset == NULL)
|
||||||
|
{
|
||||||
|
QMessageBox::about(NULL,"提示","无高程数据 ");
|
||||||
|
return NULL;//-1
|
||||||
|
}
|
||||||
|
|
||||||
|
if(viewPtDataset != objectPtDataset)
|
||||||
|
{
|
||||||
|
QMessageBox::about(NULL,"提示","观测点与被观测点不属于同一个高程数据集 ");
|
||||||
|
return NULL;//-1
|
||||||
|
}
|
||||||
|
|
||||||
|
UGDatasetRasterPtr datasetRaster = viewPtDataset;
|
||||||
|
|
||||||
|
//3D分析分析实例对象
|
||||||
|
UG3DAnalyst visAnalsyt;
|
||||||
|
UGPoint3D pntView3D,pntObject3D;
|
||||||
|
|
||||||
|
//高程值需根据x,y查询数据集得到
|
||||||
|
//得到当前测量点的高程值
|
||||||
|
// 1.首先将坐标点转换为栅格数据集对应的行和列
|
||||||
|
UGPoint pntviewImg;
|
||||||
|
double altitude;
|
||||||
|
datasetRaster->XYToImg(pntView,pntviewImg);
|
||||||
|
altitude = datasetRaster->GetValue(pntviewImg.x,pntviewImg.y);
|
||||||
|
pntView3D.x = pntView.x;
|
||||||
|
pntView3D.y = pntView.y;
|
||||||
|
pntView3D.z = altitude;
|
||||||
|
|
||||||
|
UGPoint pntObjectImg;
|
||||||
|
//坐标点转换为栅格数据集对应的行和列
|
||||||
|
datasetRaster->XYToImg(pntObject,pntObjectImg);
|
||||||
|
altitude = datasetRaster->GetValue(pntObjectImg.x,pntObjectImg.y);
|
||||||
|
pntObject3D.x = pntObject.x;
|
||||||
|
pntObject3D.y = pntObject.y;
|
||||||
|
pntObject3D.z = altitude;
|
||||||
|
|
||||||
|
//进行通视分析查询;
|
||||||
|
UG3DAnalyst::SingleResult* result = visAnalsyt.IsVisible(datasetRaster,pntView3D,pntObject3D);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
# Երկիր (Erkir) - a C++ library for geodesic and trigonometric calculations
|
||||||
|
|
||||||
|
[Erkir (armenian: Երկիր, means Earth)](https://github.com/vahancho/erkir) - is inspired
|
||||||
|
by and based on the great work of [Chris Veness](https://github.com/chrisveness),
|
||||||
|
the owner of the [Geodesy functions](https://github.com/chrisveness/geodesy)
|
||||||
|
project - provides a set of comprehensive API for geodesic and trigonometric calculations.
|
||||||
|
I would call it a C++ port of JavaScript functions provided by the mentioned Chris Veness' project,
|
||||||
|
however I designed the library to be more object oriented. Thus the code is organized a
|
||||||
|
little bit differently, but the implementation itself is preserved.
|
||||||
|
|
||||||
|
[](https://github.com/vahancho/erkir/releases)
|
||||||
|
[](https://github.com/vahancho/erkir/actions/workflows/cmake.yml)
|
||||||
|
[](https://codecov.io/gh/vahancho/erkir)
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
There are no special requirements and dependencies except *C++11* compliant compiler.
|
||||||
|
The class is tested with *gcc 4.8.4* and *MSVC 15.x* (Visual Studio 2017).
|
||||||
|
The library is written with pure STL without any third party dependencies.
|
||||||
|
For more details see the CI badges (*GitHub Actions*) above.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
No installation required. Just incorporate header files from the *include/* and
|
||||||
|
source files from *src/* directories in your project and compile them. All library
|
||||||
|
classes are in *erkir* namespace.
|
||||||
|
|
||||||
|
#### Integration with `CMake` projects
|
||||||
|
|
||||||
|
However, if you use `CMake` and want to integrate the library into your project
|
||||||
|
you might want to install it first by invoking a `CMake` command from the build directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --install . --prefix=<install_path> --config=Release
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the library is installed you can use it from in your project by adjusting its
|
||||||
|
`CMake` script. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
[..]
|
||||||
|
find_package(erkir REQUIRED)
|
||||||
|
|
||||||
|
add_executable(example main.cpp)
|
||||||
|
target_link_libraries(example erkir)
|
||||||
|
[..]
|
||||||
|
```
|
||||||
|
|
||||||
|
### The API
|
||||||
|
|
||||||
|
The code is virtually split into three domains (namespaces) that represent spherical
|
||||||
|
and ellipsoidal geodetic coordinates and cartesian (x/y/z) for geocentric ones:
|
||||||
|
`erkir::spherical`, `erkir::ellipsoidal` and `erkir::cartesian` correspondingly.
|
||||||
|
Spherical Earth model based calculations are accurate enough for most cases, however
|
||||||
|
in order to gain more precise measurements use `erkir::ellipsoidal` classes.
|
||||||
|
|
||||||
|
`erkir::spherical::Point` class implements geodetic point on the basis of a spherical
|
||||||
|
earth (ignoring ellipsoidal effects). It uses formulae to calculate distances between
|
||||||
|
two points (using haversine formula), initial bearing from a point, final bearing to a point, etc.
|
||||||
|
|
||||||
|
`erkir::ellipsoidal::Point` class represents geodetic point based on ellipsoidal
|
||||||
|
earth model. It includes ellipsoid parameters and datums for different coordinate
|
||||||
|
systems, and methods for converting between them and to Cartesian coordinates.
|
||||||
|
|
||||||
|
`erkir::Vector3d` implements 3-d vector manipulation routines. With this class you
|
||||||
|
can perform basic operations with the vectors, such as calculate dot (scalar) product
|
||||||
|
of two vectors, multiply vectors, add and subtract them.
|
||||||
|
|
||||||
|
`erkir::cartesian::Point` implements ECEF (earth-centered earth-fixed) geocentric
|
||||||
|
cartesian (x/y/z) coordinates.
|
||||||
|
|
||||||
|
### Usage Examples:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "sphericalpoint.h"
|
||||||
|
#include "ellipsoidalpoint.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// Calculate great-circle distance between two points.
|
||||||
|
erkir::spherical::Point p1{ 52.205, 0.119 };
|
||||||
|
erkir::spherical::Point p2{ 48.857, 2.351 };
|
||||||
|
auto d = p1.distanceTo(p2); // 404.3 km
|
||||||
|
|
||||||
|
// Get destination point by given distance (shortest) and bearing from start point.
|
||||||
|
erkir::spherical::Point p3{ 51.4778, -0.0015 };
|
||||||
|
auto dest = p3.destinationPoint(7794.0, 300.7); // 51.5135°N, 000.0983°W
|
||||||
|
|
||||||
|
// Convert a point from one coordinates system to another.
|
||||||
|
erkir::ellipsoidal::Point pWGS84(51.4778, -0.0016, ellipsoidal::Datum::Type::WGS84);
|
||||||
|
auto pOSGB = pWGS84.toDatum(ellipsoidal::Datum::Type::OSGB36); // 51.4778°N, 000.0000°E
|
||||||
|
|
||||||
|
// Convert to Cartesian coordinates.
|
||||||
|
auto cartesian = pWGS84.toCartesianPoint();
|
||||||
|
|
||||||
|
// Convert Cartesian point to a geodetic one.
|
||||||
|
auto geoPoint = cartesian->toGeoPoint();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more usage examples please refer to the unit tests at `/test/test.cpp` file.
|
||||||
|
|
||||||
|
### Building and Testing
|
||||||
|
|
||||||
|
There are unit tests. You can find them in the *test/* directory.
|
||||||
|
To run them you have to build and run the test application. For doing that you must invoke the following
|
||||||
|
commands from the terminal, assuming that compiler and environment are already configured:
|
||||||
|
|
||||||
|
#### Linux (gcc)
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTING=True
|
||||||
|
cmake --build .
|
||||||
|
ctest
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Windows (MSVC Toolchain)
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DENABLE_TESTING=True -A x64
|
||||||
|
cmake --build . --config=Release
|
||||||
|
ctest -C Release
|
||||||
|
```
|
||||||
|
|
||||||
|
For x86 builds use `-A Win32` option instead.
|
||||||
|
|
||||||
|
### Performance Tests
|
||||||
|
|
||||||
|
I measured performance (on Intel Core i5 series processor) for some spherical geodesy
|
||||||
|
functions (`Point` class). I used similar approach as Chris Veness did in his tests,
|
||||||
|
i.e. called functions for 5000 random points or pairs of points. And here are my results:
|
||||||
|
|
||||||
|
| Function | Avg. time/calculation (nanoseconds)|
|
||||||
|
| -------------------- |:----------------------------------:|
|
||||||
|
| Distance (haversine) | 162 |
|
||||||
|
| Initial bearing | 190 |
|
||||||
|
| Destination point | 227 |
|
||||||
|
|
||||||
|
*of course timings are machine dependent*
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
* [Movable Type Scripts Latitude/Longitude Calculations Reference](http://www.movable-type.co.uk/scripts/latlong.html)
|
||||||
|
|
@ -0,0 +1,120 @@
|
|||||||
|
/**********************************************************************************
|
||||||
|
* MIT License *
|
||||||
|
* *
|
||||||
|
* Copyright (c) 2020 Vahan Aghajanyan <vahancho@gmail.com> *
|
||||||
|
* *
|
||||||
|
* Geodesy tools for conversions between (historical) datums *
|
||||||
|
* (c) Chris Veness 2005-2019 *
|
||||||
|
* www.movable-type.co.uk/scripts/latlong-convert-coords.html *
|
||||||
|
* www.movable-type.co.uk/scripts/geodesy-library.html#latlon-ellipsoidal-datum *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal *
|
||||||
|
* in the Software without restriction, including without limitation the rights *
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included in all *
|
||||||
|
* copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
|
||||||
|
* SOFTWARE. *
|
||||||
|
***********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DATUM_H
|
||||||
|
#define DATUM_H
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace erkir
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace cartesian
|
||||||
|
{
|
||||||
|
class Point;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ellipsoidal
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Implements a geodetic datum.
|
||||||
|
/*!
|
||||||
|
Note that precision of various datums will vary, and WGS-84 (original) is not defined to be
|
||||||
|
accurate to better than ±1 metre. No transformation should be assumed to be accurate to better
|
||||||
|
than a meter; for many datums somewhat less.
|
||||||
|
*/
|
||||||
|
class ERKIR_EXPORT Datum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
ED50, /*!< The older European Datum */
|
||||||
|
Irl1975,
|
||||||
|
NAD27, /*!< The older North American Datum, of which NAD83 was basically a readjustment */
|
||||||
|
NAD83, /*!< The North American Datum which is very similar to WGS 84 */
|
||||||
|
NTF, /*!< Nouvelle Triangulation Francaise */
|
||||||
|
OSGB36, /*!< Of the Ordnance Survey of Great Britain */
|
||||||
|
Potsdam, /*!< The local datum of Germany with underlying Bessel ellipsoid */
|
||||||
|
TokyoJapan,
|
||||||
|
WGS72, /*!< 72 of the World Geodetic System */
|
||||||
|
WGS84 /*!< 84 of the World Geodetic System */
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Constructs a datum with the given \p type. WGS84 is the default datum.
|
||||||
|
Datum(Type type = Type::WGS84);
|
||||||
|
|
||||||
|
//! Implements a reference ellipsoid.
|
||||||
|
struct Ellipsoid
|
||||||
|
{
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
WGS84,
|
||||||
|
Airy1830,
|
||||||
|
AiryModified,
|
||||||
|
Bessel1841,
|
||||||
|
Clarke1866,
|
||||||
|
Clarke1880IGN,
|
||||||
|
GRS80,
|
||||||
|
Intl1924, // aka Hayford
|
||||||
|
WGS72
|
||||||
|
};
|
||||||
|
|
||||||
|
Ellipsoid(double a, double b, double f);
|
||||||
|
|
||||||
|
/// Major axis (a).
|
||||||
|
double m_a{0.0};
|
||||||
|
|
||||||
|
/// Minor axis (b).
|
||||||
|
double m_b{0.0};
|
||||||
|
|
||||||
|
/// Flattening (f).
|
||||||
|
double m_f{0.0};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Returns the reference ellipsoid for this datum.
|
||||||
|
const Ellipsoid &ellipsoid() const;
|
||||||
|
|
||||||
|
/// Returns the type of this datum.
|
||||||
|
Type type() const;
|
||||||
|
|
||||||
|
/// Converts the given cartesian \p point to the \p targetDatum.
|
||||||
|
void toDatum(cartesian::Point &point, Type targetDatum) const;
|
||||||
|
|
||||||
|
/// Compares two datums.
|
||||||
|
bool operator==(const Datum &other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type m_type{Type::WGS84};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // ellipsoidal
|
||||||
|
|
||||||
|
} // erkir
|
||||||
|
|
||||||
|
#endif // DATUM_H
|
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __EXPORT_H_
|
||||||
|
#define __EXPORT_H_
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef MAKEDLL
|
||||||
|
# define ERKIR_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define ERKIR_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define ERKIR_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __EXPORT_H_
|
@ -0,0 +1,70 @@
|
|||||||
|
/**********************************************************************************
|
||||||
|
* MIT License *
|
||||||
|
* *
|
||||||
|
* Copyright (c) 2018-2019 Vahan Aghajanyan <vahancho@gmail.com> *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal *
|
||||||
|
* in the Software without restriction, including without limitation the rights *
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is *
|
||||||
|
* furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included in all *
|
||||||
|
* copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
|
||||||
|
* SOFTWARE. *
|
||||||
|
***********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef POINT_H
|
||||||
|
#define POINT_H
|
||||||
|
|
||||||
|
#include "coordinate.h"
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace erkir
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Base class for all types of geodetic points.
|
||||||
|
class ERKIR_EXPORT Point
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Constructs an invalid point object.
|
||||||
|
Point();
|
||||||
|
|
||||||
|
//! Constructs a point with the given \p latitude and \p longitude.
|
||||||
|
Point(const Latitude &latitude, const Longitude &longitude);
|
||||||
|
|
||||||
|
//! Returns the latitude of this point.
|
||||||
|
const Latitude &latitude() const;
|
||||||
|
|
||||||
|
//! Returns the longitude of this point.
|
||||||
|
const Longitude &longitude() const;
|
||||||
|
|
||||||
|
//! Returns true if this point is a valid one and false otherwise.
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
/// Returns true if two points are equal and false otherwise.
|
||||||
|
bool operator==(const Point &other) const;
|
||||||
|
|
||||||
|
/// Returns true if two points are different and false otherwise.
|
||||||
|
bool operator!=(const Point &other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Latitude m_latitude;
|
||||||
|
Longitude m_longitude;
|
||||||
|
bool m_isValid;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // erkir
|
||||||
|
|
||||||
|
#endif // POINT_H
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue