Solves all kinds of geographical position calculations.
Project description
nvector
The nvector library is a suite of tools written in Python to solve geographical position calculations. Currently the following operations are implemented:
 Calculate the surface distance between two geographical positions.
 Convert positions given in one reference frame into another reference frame.
 Find the destination point given start point, azimuth/bearing and distance.
 Find the mean position (center/midpoint) of several geographical positions.
 Find the intersection between two paths.
 Find the cross track distance between a path and a position.
Using nvector, the calculations become simple and nonsingular. Full accuracy is achieved for any global position (and for any distance).
Description
In this library, we represent position with an “nvector”, which is the normal vector to the Earth model (the same reference ellipsoid that is used for latitude and longitude). When using nvector, all Earthpositions are treated equally, and there is no need to worry about singularities or discontinuities. An additional benefit with using nvector is that many position calculations can be solved with simple vector algebra (e.g. dot product and cross product).
Converting between nvector and latitude/longitude is unambiguous and easy using the provided functions.
n_E is nvector in the program code, while in documents we use nE. E denotes an Earthfixed coordinate frame, and it indicates that the three components of nvector are along the three axes of E. More details about the notation and reference frames can be found in the documentation.
Documentation and code
Official documentation:
http://www.navlab.net/nvector/
http://nvector.readthedocs.io/en/latest/
 Kenneth Gade (2010):
 A Nonsingular Horizontal Position Representation, The Journal of Navigation, Volume 63, Issue 03, pp 395417, July 2010.
Bleeding edge: https://github.com/pbrod/nvector.
Official releases available at: http://pypi.python.org/pypi/nvector.
Install nvector
If you have pip installed and are online, then simply type:
$ pip install nvector
to get the lastest stable version. Using pip also has the advantage that all requirements are automatically installed.
You can download nvector and all dependencies to a folder “pkg”, by the following:
$ pip install –download=pkg nvector
To install the downloaded nvector, just type:
$ pip install –noindex –findlinks=pkg nvector
Verifying installation
To verify that nvector can be seen by Python, type python from your shell. Then at the Python prompt, try to import nvector:
>>> import nvector as nv >>> print(nv.__version__) 0.7.6
To test if the toolbox is working correctly paste the following in an interactive python session:
import nvector as nv nv.test('doctestmodules')
or
$ py.test –pyargs nvector –doctestmodules
at the command prompt.
Getting Started
Below the objectoriented solution to some common geodesic problems are given. In the first example the functional solution is also given. The functional solutions to the remaining problems can be found in the functional examples section of the tutorial.
Example 1: “A and B to delta”
Given two positions, A and B as latitudes, longitudes and depths relative to Earth, E.
Find the exact vector between the two positions, given in meters north, east, and down, and find the direction (azimuth) to B, relative to north. Assume WGS84 ellipsoid. The given depths are from the ellipsoid surface. Use position A to define north, east, and down directions. (Due to the curvature of Earth and different directions to the North Pole, the north, east, and down directions will change (relative to Earth) for different places. A must be outside the poles for the north and east directions to be defined.)
 Solution:
>>> import numpy as np >>> import nvector as nv >>> wgs84 = nv.FrameE(name='WGS84') >>> pointA = wgs84.GeoPoint(latitude=1, longitude=2, z=3, degrees=True) >>> pointB = wgs84.GeoPoint(latitude=4, longitude=5, z=6, degrees=True)
 Step1: Find p_AB_N (delta decomposed in N).
>>> p_AB_N = pointA.delta_to(pointB) >>> x, y, z = p_AB_N.pvector.ravel() >>> valtxt = '{0:8.2f}, {1:8.2f}, {2:8.2f}'.format(x, y, z) >>> 'Ex1: delta north, east, down = {}'.format(valtxt) 'Ex1: delta north, east, down = 331730.23, 332997.87, 17404.27'
 Step2: Also find the direction (azimuth) to B, relative to north:
>>> azimuth = p_AB_N.azimuth_deg >>> 'azimuth = {0:4.2f} deg'.format(azimuth) 'azimuth = 45.11 deg'
 Functional Solution:
>>> import numpy as np >>> import nvector as nv >>> from nvector import rad, deg
>>> lat_EA, lon_EA, z_EA = rad(1), rad(2), 3 >>> lat_EB, lon_EB, z_EB = rad(4), rad(5), 6
 Step1: Convert to nvectors:
>>> n_EA_E = nv.lat_lon2n_E(lat_EA, lon_EA) >>> n_EB_E = nv.lat_lon2n_E(lat_EB, lon_EB)
 Step2: Find p_AB_E (delta decomposed in E).WGS84 ellipsoid is default:
>>> p_AB_E = nv.n_EA_E_and_n_EB_E2p_AB_E(n_EA_E, n_EB_E, z_EA, z_EB)
 Step3: Find R_EN for position A:
>>> R_EN = nv.n_E2R_EN(n_EA_E)
 Step4: Find p_AB_N (delta decomposed in N).
>>> p_AB_N = np.dot(R_EN.T, p_AB_E).ravel() >>> valtxt = '{0:8.2f}, {1:8.2f}, {2:8.2f}'.format(*p_AB_N) >>> 'Ex1: delta north, east, down = {}'.format(valtxt) 'Ex1: delta north, east, down = 331730.23, 332997.87, 17404.27'
 Step5: Also find the direction (azimuth) to B, relative to north:
>>> azimuth = np.arctan2(p_AB_N[1], p_AB_N[0]) >>> 'azimuth = {0:4.2f} deg'.format(deg(azimuth)) 'azimuth = 45.11 deg'
 See also
 Example 1 at www.navlab.net
Example 2: “B and delta to C”
A radar or sonar attached to a vehicle B (Body coordinate frame) measures the distance and direction to an object C. We assume that the distance and two angles (typically bearing and elevation relative to B) are already combined to the vector p_BC_B (i.e. the vector from B to C, decomposed in B). The position of B is given as n_EB_E and z_EB, and the orientation (attitude) of B is given as R_NB (this rotation matrix can be found from roll/pitch/yaw by using zyx2R).
Find the exact position of object C as nvector and depth ( n_EC_E and z_EC ), assuming Earth ellipsoid with semimajor axis a and flattening f. For WGS72, use a = 6 378 135 m and f = 1/298.26.
 Solution:
>>> import numpy as np >>> import nvector as nv >>> wgs72 = nv.FrameE(name='WGS72') >>> wgs72 = nv.FrameE(a=6378135, f=1.0/298.26)
 Step 1: Position and orientation of B is given 400m above E:
>>> n_EB_E = wgs72.Nvector(nv.unit([[1], [2], [3]]), z=400) >>> frame_B = nv.FrameB(n_EB_E, yaw=10, pitch=20, roll=30, degrees=True)
 Step 2: Delta BC decomposed in B
>>> p_BC_B = frame_B.Pvector(np.r_[3000, 2000, 100].reshape((1, 1)))
 Step 3: Decompose delta BC in E
>>> p_BC_E = p_BC_B.to_ecef_vector()
 Step 4: Find point C by adding delta BC to EB
>>> p_EB_E = n_EB_E.to_ecef_vector() >>> p_EC_E = p_EB_E + p_BC_E >>> pointC = p_EC_E.to_geo_point()
>>> lat, lon, z = pointC.latlon_deg >>> msg = 'Ex2: PosC: lat, lon = {:4.2f}, {:4.2f} deg, height = {:4.2f} m' >>> msg.format(lat, lon, z) 'Ex2: PosC: lat, lon = 53.33, 63.47 deg, height = 406.01 m'
 See also
 Example 2 at www.navlab.net
Example 3: “ECEFvector to geodetic latitude”
Position B is given as an “ECEFvector” p_EB_E (i.e. a vector from E, the center of the Earth, to B, decomposed in E). Find the geodetic latitude, longitude and height (latEB, lonEB and hEB), assuming WGS84 ellipsoid.
 Solution:
>>> import numpy as np >>> import nvector as nv >>> wgs84 = nv.FrameE(name='WGS84') >>> position_B = 6371e3 * np.vstack((0.9, 1, 1.1)) # m >>> p_EB_E = wgs84.ECEFvector(position_B) >>> pointB = p_EB_E.to_geo_point()
>>> lat, lon, z = pointB.latlon_deg >>> msg = 'Ex3: Pos B: lat, lon = {:4.2f}, {:4.2f} deg, height = {:9.2f} m' >>> msg.format(lat, lon, z) 'Ex3: Pos B: lat, lon = 39.38, 48.01 deg, height = 4702059.83 m'
 See also
 Example 3 at www.navlab.net
Example 4: “Geodetic latitude to ECEFvector”
Geodetic latitude, longitude and height are given for position B as latEB, lonEB and hEB, find the ECEFvector for this position, p_EB_E.
 Solution:
>>> import nvector as nv >>> wgs84 = nv.FrameE(name='WGS84') >>> pointB = wgs84.GeoPoint(latitude=1, longitude=2, z=3, degrees=True) >>> p_EB_E = pointB.to_ecef_vector()
>>> 'Ex4: p_EB_E = {} m'.format(p_EB_E.pvector.ravel().tolist()) 'Ex4: p_EB_E = [6373290.277218279, 222560.20067473652, 110568.82718178593] m'
 See also
 Example 4 at www.navlab.net
Example 5: “Surface distance”
Find the surface distance sAB (i.e. great circle distance) between two positions A and B. The heights of A and B are ignored, i.e. if they don’t have zero height, we seek the distance between the points that are at the surface of the Earth, directly above/below A and B. The Euclidean distance (chord length) dAB should also be found. Use Earth radius 6371e3 m. Compare the results with exact calculations for the WGS84 ellipsoid.
 Solution for a sphere:
>>> import numpy as np >>> import nvector as nv >>> frame_E = nv.FrameE(a=6371e3, f=0) >>> positionA = frame_E.GeoPoint(latitude=88, longitude=0, degrees=True) >>> positionB = frame_E.GeoPoint(latitude=89, longitude=170, degrees=True)
>>> s_AB, _azia, _azib = positionA.distance_and_azimuth(positionB) >>> p_AB_E = positionB.to_ecef_vector()  positionA.to_ecef_vector() >>> d_AB = p_AB_E.length
>>> msg = 'Ex5: Great circle and Euclidean distance = {}' >>> msg = msg.format('{:5.2f} km, {:5.2f} km') >>> msg.format(s_AB / 1000, d_AB / 1000) 'Ex5: Great circle and Euclidean distance = 332.46 km, 332.42 km'
 Alternative sphere solution:
>>> path = nv.GeoPath(positionA, positionB) >>> s_AB2 = path.track_distance(method='greatcircle') >>> d_AB2 = path.track_distance(method='euclidean') >>> msg.format(s_AB2 / 1000, d_AB2 / 1000) 'Ex5: Great circle and Euclidean distance = 332.46 km, 332.42 km'
 Exact solution for the WGS84 ellipsoid:
>>> wgs84 = nv.FrameE(name='WGS84') >>> point1 = wgs84.GeoPoint(latitude=88, longitude=0, degrees=True) >>> point2 = wgs84.GeoPoint(latitude=89, longitude=170, degrees=True) >>> s_12, _azi1, _azi2 = point1.distance_and_azimuth(point2)
>>> p_12_E = point2.to_ecef_vector()  point1.to_ecef_vector() >>> d_12 = p_12_E.length >>> msg = 'Ellipsoidal and Euclidean distance = {:5.2f} km, {:5.2f} km' >>> msg.format(s_12 / 1000, d_12 / 1000) 'Ellipsoidal and Euclidean distance = 333.95 km, 333.91 km'
 See also
 Example 5 at www.navlab.net
Example 6 “Interpolated position”
Given the position of B at time t0 and t1, n_EB_E(t0) and n_EB_E(t1).
Find an interpolated position at time ti, n_EB_E(ti). All positions are given as nvectors.
 Solution:
>>> import nvector as nv >>> wgs84 = nv.FrameE(name='WGS84') >>> n_EB_E_t0 = wgs84.GeoPoint(89, 0, degrees=True).to_nvector() >>> n_EB_E_t1 = wgs84.GeoPoint(89, 180, degrees=True).to_nvector() >>> path = nv.GeoPath(n_EB_E_t0, n_EB_E_t1)
>>> t0 = 10. >>> t1 = 20. >>> ti = 16. # time of interpolation >>> ti_n = (ti  t0) / (t1  t0) # normalized time of interpolation
>>> g_EB_E_ti = path.interpolate(ti_n).to_geo_point()
>>> lat_ti, lon_ti, z_ti = g_EB_E_ti.latlon_deg >>> msg = 'Ex6, Interpolated position: lat, lon = {:2.1f} deg, {:2.1f} deg' >>> msg.format(lat_ti, lon_ti) 'Ex6, Interpolated position: lat, lon = 89.8 deg, 180.0 deg'
 See also
 Example 6 at www.navlab.net
Example 7: “Mean position”
Three positions A, B, and C are given as nvectors n_EA_E, n_EB_E, and n_EC_E. Find the mean position, M, given as n_EM_E. Note that the calculation is independent of the depths of the positions.
 Solution:
>>> import nvector as nv >>> points = nv.GeoPoint(latitude=[90, 60, 50], ... longitude=[0, 10, 20], degrees=True) >>> nvectors = points.to_nvector() >>> n_EM_E = nvectors.mean() >>> g_EM_E = n_EM_E.to_geo_point() >>> lat, lon = g_EM_E.latitude_deg, g_EM_E.longitude_deg >>> msg = 'Ex7: Pos M: lat, lon = {:4.2f}, {:4.2f} deg' >>> msg.format(lat, lon) 'Ex7: Pos M: lat, lon = 67.24, 6.92 deg'
 See also
 Example 7 at www.navlab.net
Example 8: “A and azimuth/distance to B”
We have an initial position A, direction of travel given as an azimuth (bearing) relative to north (clockwise), and finally the distance to travel along a great circle given as sAB. Use Earth radius 6371e3 m to find the destination point B.
In geodesy this is known as “The first geodetic problem” or “The direct geodetic problem” for a sphere, and we see that this is similar to Example 2, but now the delta is given as an azimuth and a great circle distance. (“The second/inverse geodetic problem” for a sphere is already solved in Examples 1 and 5.)
 Solution:
>>> import nvector as nv >>> frame = nv.FrameE(a=6371e3, f=0) >>> pointA = frame.GeoPoint(latitude=80, longitude=90, degrees=True) >>> pointB, _azimuthb = pointA.displace(distance=1000, azimuth=200, degrees=True) >>> lat, lon = pointB.latitude_deg, pointB.longitude_deg
>>> msg = 'Ex8, Destination: lat, lon = {:4.2f} deg, {:4.2f} deg' >>> msg.format(lat, lon) 'Ex8, Destination: lat, lon = 79.99 deg, 90.02 deg'
 See also
 Example 8 at www.navlab.net
Example 9: “Intersection of two paths”
Define a path from two given positions (at the surface of a spherical Earth), as the great circle that goes through the two points.
Path A is given by A1 and A2, while path B is given by B1 and B2.
Find the position C where the two great circles intersect.
 Solution:
>>> import numpy as np >>> import nvector as nv >>> pointA1 = nv.GeoPoint(10, 20, degrees=True) >>> pointA2 = nv.GeoPoint(30, 40, degrees=True) >>> pointB1 = nv.GeoPoint(50, 60, degrees=True) >>> pointB2 = nv.GeoPoint(70, 80, degrees=True) >>> pathA = nv.GeoPath(pointA1, pointA2) >>> pathB = nv.GeoPath(pointB1, pointB2)
>>> pointC = pathA.intersect(pathB) >>> np.allclose(pathA.on_path(pointC), pathB.on_path(pointC)) True >>> np.allclose(pathA.on_great_circle(pointC), ... pathB.on_great_circle(pointC)) True >>> pointC = pointC.to_geo_point() >>> lat, lon = pointC.latitude_deg, pointC.longitude_deg >>> msg = 'Ex9, Intersection: lat, lon = {:4.2f}, {:4.2f} deg' >>> msg.format(lat, lon) 'Ex9, Intersection: lat, lon = 40.32, 55.90 deg'
 See also
 Example 9 at www.navlab.net
Example 10: “Cross track distance”
Path A is given by the two positions A1 and A2 (similar to the previous example).
Find the cross track distance sxt between the path A (i.e. the great circle through A1 and A2) and the position B (i.e. the shortest distance at the surface, between the great circle and B).
Also find the Euclidean distance dxt between B and the plane defined by the great circle. Use Earth radius 6371e3.
Finally, find the intersection point on the great circle and determine if it is between position A1 and A2.
 Solution:
>>> import numpy as np >>> import nvector as nv >>> frame = nv.FrameE(a=6371e3, f=0) >>> pointA1 = frame.GeoPoint(0, 0, degrees=True) >>> pointA2 = frame.GeoPoint(10, 0, degrees=True) >>> pointB = frame.GeoPoint(1, 0.1, degrees=True) >>> pathA = nv.GeoPath(pointA1, pointA2)
>>> s_xt = pathA.cross_track_distance(pointB, method='greatcircle') >>> d_xt = pathA.cross_track_distance(pointB, method='euclidean')
>>> val_txt = '{:4.2f} km, {:4.2f} km'.format(s_xt/1000, d_xt/1000) >>> 'Ex10: Cross track distance: s_xt, d_xt = {}'.format(val_txt) 'Ex10: Cross track distance: s_xt, d_xt = 11.12 km, 11.12 km'
>>> pointC = pathA.closest_point_on_great_circle(pointB) >>> np.allclose(pathA.on_path(pointC), True) True
 See also
 Example 10 at www.navlab.net
Acknowledgements
The nvector package for Python was written by Per A. Brodtkorb at FFI (The Norwegian Defence Research Establishment) based on the nvector toolbox for Matlab written by the navigation group at FFI. The nvector.core and nvector.rotation module is a vectorized reimplementation of the matlab nvector toolbox while the nvector.objects module is a new easy to use object oriented user interface to the nvector core functionality documented in [GB20].
Most of the content is based on the article by K. Gade [Gad10].
Thus this article should be cited in publications using this page or downloaded program code.
However, if you use any of the FrameE.direct, FrameE.inverse, GeoPoint.distance_and_azimuth or GeoPoint.displace methods you should also cite the article by Karney [Kar13] because these methods call Karney’s geographiclib library to do the calculations.
References
[Gad10]  K. Gade, A Nonsingular Horizontal Position Representation, J. Navigation, 63(3):395417, 2010. 
[Kar13]  C.F.F. Karney. Algorithms for geodesics. J. Geodesy, 87(1):4355, 2013. 
[GB20]  K. Gade and P.A. Brodtkorb, Nvector Documentation for Python, 2020. 
Changelog
Version 0.7.6, December 18, 2020
 Per A Brodtkorb (30):
 Renamed _core.py to core.py
 Removed the module index from the appendix because it was incomplete.
 Removed nvector.tests package from the reference chapter.
 Added indent function to _common.py to avoid failure on python 2.7.
 Moved isclose, allclose and array_to_list_dict from objects.py to util.py
 Moved the following function from test_nvector.py to test_rotation.py:
 test_n_E_and_wa2R_EL, test_R2zxy, test_R2zxy_x90, test_R2zxy_y90
 test_R2zxy_z90, test_R2zxy_0, test_R2xyz test_R2xyz_with_vectors
 Replaced assert_array_almost_equal with assert_allclose in test_objects.py
 Renamed test_frames.py to test_objects.py
 Added missing functions great_circle_normal and interpolate to the nvector_summary.rst
 Moved the following functions related to rotation matrices from _core to rotation module:
 E_rotation, n_E_and_wa2R_EL, n_E2R_EN, R_EL2n_E, R_EN2n_E, R2xyz, R2zyx, xyz2R, zyx2R
 Renamed select_ellipsoid to get_ellipsoid
 Moved the following utility functions from _core to util module:
 deg, rad, mdot, nthroot, get_ellipsoid, unit, _check_length_deviation
 Added _get_h1line and _make_summary to _common.py
 Replaced numpy.rollaxis with numpy.swapaxes to make the code clearer.
 _atleast_3d now broadcast the input against each other.
 Added examples to zyx2R
 Added the following references to zyx2R, xyz2R, R2xyz, R2zyx:
 Removed tabs from CHANGELOG.rst
 Updated CHANGELOG.rst and prepared for release v0.7.6
 Fixed the documentation so that it shows correctly in the reference manual.
 Added logo.png and docs/reference/nvector.rst
 Updated build_package.py so it generates a valid README.rst file.
 Updated THANKS.rst
 Updated CHANGELOG.rst and prepare for release 0.7.6
 Added Nvector documentation ref https://nvector.readthedocs.io/en/v0.7.5 to refs1.bib and _acknowledgements.py
 Updated README.rst
 Renamed requirements.readthedocs.txt to docs/requirements.txt
 Added .readthedocs.yml
 Added sphinxcontribbibtex to requirements.readthedocs.txt
 Added missing docs/tutorials/images/ex3img.png
 Deleted obsolete ex10img.png
 Updated acknowledgement with reference to Karney’s article.
 Updated README.rst by moving acknowledgement to the end with references.
 Renamed position input argument to point in the FrameN, FrameB and FrameL classes.
 Deleted _example_images.py
 Renamed nvector.rst to nvector_summary.rst in docs/reference
 Added example images to tutorials/images/ folder
 Added Nvector logo, install.rst to docs
 Added src/nvector/_example_images.py
 Added docs/tutorials/whatsnext.rst
 Reorganized the documentation in docs by splitting _info.py into:
 _intro.py,
 _documentation.py
 _examples_object_oriented.py
 _images.py
 _installation.py and _acknowledgements.py
 Added docs/tutorials/index.rst, docs/intro/index.rst, docs/howto/index.rst docs/appendix/index.rst and docs/make.bat
 updated references.
Version 0.7.5, December 12, 2020
 Per A Brodtkorb (32):
 Updated CHANGELOG.rst and prepare for release 0.7.5
 Changed so that GeoPath.on_great_circle and GeoPath.on_great_circle
 returns scalar result if the two points defining the path are scalars. See issue #10.
 Fixed failing doctests.
 Added doctest configuration to docs/conf.py
 Added allclose to nvector/objects.py
 Added array_to_list_dict and isclose functions in nvector.objects.py
 Replaced fstring in the __repr__ method of the _Common class in nvector.objects.py with format in order to work on python version 3.5 and below.
 Made nvector.plot.py more robust.
 Removed rtol parameter from the on_greatcircle function. See issue #12 for a discussion.
 Added nvector solution to the GeoPoint.displace method.
 Updated docs/conf.py
 Updated README.rst and LICENSE.txt
 Replaced import unittest with import pytest in test_frames.py
 Fixed issue #10: Inconsistent return types in GeoPath.track_distance:
 GeoPath, GeoPoint, Nvector and ECEFvector and Pvector now return scalars for the case where the input is not actually arrays of points but just single objects.
 Added extra tests for issue #10 and updated old tests and the examples in the help headers.
 Vectorized FrameE.inverse and FrameE.direct methods.
 Extended deg and rad functions in _core.py.
 Vectorized GeoPoint.distance_and_azimuth
 Made import of cartopy in nvector.plot more robust.
 Updated test_Ex10_cross_track_distance
 Updated sonarproject.properties
 Replaced deprecated sonar.XXXX.reportPath with sonar.XXXX.reportPaths
 Simplified nvector/_core.__doc__
 Updated .travis.yml
 Changed the definition of sonar addon
 Added CC_TEST_REPORTER_ID to .travis.yml
 Added python 3.8 to the CI testing.
 Changed so that setup.py is python 2.7 compatible again.
 Updated build_package.py
 Renamed CHANGES.rst to CHANGELOG.rst
 Updated setup.cfg and setup.py
 Added license.py
 Updated build_package.py
 Removed condabuild from .travis.yml
 Attempt to get travis to run the tests again….
 API change: replaced “python setup.py doctests” with “python setup.py doctest”
 Added doctest example to nvector._core._atleast_3d Made xyz2R and zyx2R code simpler.
 Replaced deprecated Nvector.mean_horizontal_position with Nvector.mean in test_frames.py
 Added mdot to __all__ in nvector/_core.py and in documentation summary.
 Sorted the the documentation summary by function name in nvector.rst
 Removed –pyargs nvector –doctestmodules –pep8 from addopts section in setup.cfg
 Updated documentation and added missing documentation.
Version 0.7.4, June 4, 2019
 Per A Brodtkorb (2):
 Fixed PyPi badge and added downloads badge in nvector/_info.py and README.rst
 Removed obsolete and wrong badges from docs/index.rst
Version 0.7.3, June 4, 2019
 Per A Brodtkorb (6):
 Renamed LICENSE.txt and THANKS.txt to LICENSE.rst and THANKS.rst
 Updated README.rst and nvector/_info.py
 Fixed issue 7# incorrect test for test_n_E_and_wa2R_EL.
 Removed coveralls test coverage report.
 Replaced coverage badge from coveralls to codecov.
 Updated codeclimate reporter.
 Simplified duplicated code in nvector._core.
 Added tests/__init__.py
 Added “–pyargs nvector” to pytest options in setup.cfg
 Exclude build_package.py from distribution in MANIFEST.in
 Replaced health_img from landscape to codeclimate.
 Updated travis to explicitly install pytestcov and pytestpep8
 Removed dependence on pyscaffold
 Added MANIFEST.in
 Renamed set_package_version.py to build_package.py
Version 0.7.0, June 2, 2019
 Gary van der Merwe (1):
 Add interpolate to __all__ so that it can be imported
 Per A Brodtkorb (26):
 Updated long_description in setup.cfg
 Replaced deprecated sphinx.ext.pngmath with sphinx.ext.imgmath
 Added imgmath to requirements for building the docs.
 Fixing shallow clone warning.
 Replaced property ‘sonar.python.coverage.itReportPath’ with
 ‘sonar.python.coverage.reportPaths’ instead, because it is has been removed.
 Drop python 3.4 support
 Added python 3.7 support
 Fixed a bug: Mixed scalars and np.array([1]) values don’t work with np.rad2deg function.
 Added ETRS ELLIPSOID in _core.py Added ED50 as alias for International
 (Hayford)/European Datum in _core.py Added sad69 as alias for South American 1969 in _core.py
 Simplified docstring for nv.test
 Generalized the setup.py.
 Replaced aliases with the correct names in setup.cfg.
Version 0.6.0, December 9, 2018
 Per A Brodtkorb (79):
 Updated requirements in setup.py
 Removed tox.ini
 Updated documentation on how to set package version
 Made a separate script to set package version in nvector/__init__.py
 Updated docstring for select_ellipsoid
 Replace GeoPoint.geo_point with GeoPoint.displace and removed deprecated GeoPoint.geo_point
 Update .travis.yml
 Fix so that codeclimate is able to parse .travis.yml
 Only run sonar and codeclimate reporter for python v3.6
 Added sonarproject.properties
 Pinned coverage to v4.3.4 due to fact that codeclimate reporter is only
 compatible with Coverage.py versions >=4.0,<4.4.
 Updated with sonar scanner.
 Added .pylintrc
 Set up codeclimate reporter
 Updated docstring for unit function.
 Avoid division by zero in unit function.
 Reenabled the doctest of plot_mean_position
 Reset “pyscaffold==2.5.11”
 Replaced deprecated basemap with cartopy.
 Replaced doctest of plot_mean_position with test_plot_mean_position in
 test_plot.py
 Fixed failing doctests for python v3.4 and v3.5 and made them more
 robust.
 Fixed failing doctests and made them more robust.
 Increased pycoverage version to use.
 moved nvector to src/nvector/
 Reset the setup.py to require ‘pyscaffold==2.5.11’ which works on
 python version 3.4, 3.5 and 3.6. as well as 2.7
 Updated unittests.
 Updated tests.
 Removed obsolete code
 Added test for delta_L
 Added corner testcase for
 pointA.displace(distance=1000,azimuth=np.deg2rad(200))
 Added test for path.track_distance(method=’exact’)
 Added delta_L a function thet teturn cartesian delta vector from
 positions A to B decomposed in L.
 Simplified OOsolution in example 1 by using delta_N function
 Refactored duplicated code
 Vectorized code so that the frames can take more than one position at
 the time.
 Keeping only the html docs in the distribution.
 replaced link from latest to stable docs on readthedocs and updated
 crosstrack distance test.
 updated documentation in setup.py
Version 0.5.2, March 7, 2017
 Per A Brodtkorb (10):
 Fixed tests in tests/test_frames.py
 Updated to setup.cfg and tox.ini + pep8
 updated .travis.yml
 Updated Readme.rst with new example 10 picture and link to nvector docs at readthedocs.
 updated official documentation links
 Updated crosstrack distance tests.
Version 0.5.1, March 5, 2017
 Cody (4):
 Explicitely numbered replacement fields
 Migrated % string formating
 Per A Brodtkorb (29):
 pep8
 Updated failing examples
 Updated README.rst
 Removed obsolete pass statement
 Documented functions
 added .checkignore for quantifycode
 moved test_docstrings and use_docstring_from into _common.py
 Added .codeclimate.yml
 Updated installation information in _info.py
 Added GeoPath.on_path method. Clearified intersection example
 Added great_circle_normal, cross_track_distance
 Renamed intersection to intersect (Intersection is deprecated.)
 Simplified R2zyx with a call to R2xyz Improved accuracy for great circle cross track distance for small distances.
 Added on_great_circle, _on_great_circle_path, _on_ellipsoid_path, closest_point_on_great_circle and closest_point_on_path to GeoPath
 made __eq__ more robust for frames
 Removed duplicated code
 Updated tests
 Removed fishy test
 replaced zero nvector with nan
 Commented out failing test.
 Added example 10 image
 Added ‘closest_point_on_great_circle’, ‘on_great_circle’,’on_great_circle_path’.
 Updated examples + documentation
 Updated index depth
 Updated README.rst and classifier in setup.cfg
Version 0.4.1, January 19, 2016
pbrod (46):
 Cosmetic updates
 Updated README.rst
 updated docs and removed unused code
 updated README.rst and .coveragerc
 Refactored out _check_frames
 Refactored out _default_frame
 Updated .coveragerc
 Added link to geographiclib
 Updated external link
 Updated documentation
 Added figures to examples
 Added GeoPath.interpolate + interpolation example 6
 Added links to FFI homepage.
 Updated documentation:
 Added link to nvector toolbox for matlab
 For each example added links to the more detailed explanation on the homepage
 Updated link to nvector toolbox for matlab
 Added link to nvector on pypi
 Updated documentation fro FrameB, FrameE, FrameL and FrameN.
 updated __all__ variable
 Added missing R_Ee to function n_EA_E_and_n_EB_E2azimuth + updated documentation
 Updated CHANGES.rst
 Updated conf.py
 Renamed info.py to _info.py
 All examples are now generated from _examples.py.
Version 0.1.3, January 1, 2016
pbrod (31):
 Refactored
 Updated tests
 Updated docs
 Moved tests to nvector/tests
 Updated .coverage Added travis.yml, .landscape.yml
 Deleted obsolete LICENSE
 Updated README.rst
 Removed ngs version
 Fixed bug in .travis.yml
 Updated .travis.yml
 Removed dependence on navigator.py
 Updated README.rst
 Updated examples
 Deleted skeleton.py and added tox.ini
 Renamed distance_rad_bearing_rad2point to n_EA_E_distance_and_azimuth2n_EB_E
 Renamed azimuth to n_EA_E_and_n_EB_E2azimuth
 Added tests for R2xyz as well as R2zyx
 Removed backward compatibility
 Added test_n_E_and_wa2R_EL
 Refactored tests
 Commented out failing tests on python 3+
 updated CHANGES.rst
 Removed bug in setup.py
Version 0.1.1, January 1, 2016
 pbrod (31):
 Initial commit: Translated code from Matlab to Python.
 Added object oriented interface to nvector library
 Added tests for object oriented interface
 Added geodesic tests.
The content of this library is based on the following publication:
Gade, K. (2010). A Nonsingular Horizontal Position Representation, The Journal of Navigation, Volume 63, Issue 03, pp 395417, July 2010. (www.navlab.net/Publications/A_Nonsingular_Horizontal_Position_Representation.pdf)
This paper should be cited in publications using this library.
Copyright (c) 20152020, Norwegian Defence Research Establishment (FFI) All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above publication information, copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above publication information, copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Contributers
 Kenneth Gade, FFI: Main author of Matlab toolbox nvector.
 Kristian Svartveit, FFI: Contributions to matlab code: R_Ee.m and unit.m.
 Brita Hafskjold Gade, FFI: Contributions to matlab code: n_EB_E2p_EB_E.m, p_EB_E2n_EB_E.m
 Per A Brodtkorb, FFI: Translation of nvector from matlab to Python and maintainer of the python version.
Project details
Release history Release notifications  RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size  File type  Python version  Upload date  Hashes 

Filename, size nvector0.7.6py2.py3noneany.whl (68.9 kB)  File type Wheel  Python version py2.py3  Upload date  Hashes View 
Filename, size nvector0.7.6.tar.gz (7.9 MB)  File type Source  Python version None  Upload date  Hashes View 
Hashes for nvector0.7.6py2.py3noneany.whl
Algorithm  Hash digest  

SHA256  7c4973909c3ea2df62c3683f7486387f57d51bf8e257586ec3a0035ecd7c91b7 

MD5  fd3940e572140bfbf19e46aa28dde9f5 

BLAKE2256  4712d8a8e79ddb98ab9ed6c81dc47b450ba37d7a62d2d06a088cbe6b744ad800 