{"id":34060897,"url":"https://github.com/mhogan-nwra/envector","last_synced_at":"2026-04-06T02:31:32.893Z","repository":{"id":255421791,"uuid":"849566031","full_name":"mhogan-nwra/envector","owner":"mhogan-nwra","description":"The envector package is a suite of tools written in Python forked from the nvector package to solve geographical position calculations powered by means of n-vector.","archived":false,"fork":false,"pushed_at":"2024-09-18T19:46:58.000Z","size":656,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-12-16T01:11:47.314Z","etag":null,"topics":["coordinates","coordinates-transformations","ecef","geodesic","geodesy","geographic","geospatial","gps","great-circle","lla","n-vector","python","wgs84"],"latest_commit_sha":null,"homepage":"https://www.navlab.net/nvector","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mhogan-nwra.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-29T20:29:13.000Z","updated_at":"2025-09-28T21:46:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"e86d569a-c538-49cc-bdbf-f381e0e9ed28","html_url":"https://github.com/mhogan-nwra/envector","commit_stats":null,"previous_names":["mhogan-nwra/envector"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mhogan-nwra/envector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhogan-nwra%2Fenvector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhogan-nwra%2Fenvector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhogan-nwra%2Fenvector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhogan-nwra%2Fenvector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhogan-nwra","download_url":"https://codeload.github.com/mhogan-nwra/envector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhogan-nwra%2Fenvector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31457513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coordinates","coordinates-transformations","ecef","geodesic","geodesy","geographic","geospatial","gps","great-circle","lla","n-vector","python","wgs84"],"created_at":"2025-12-14T04:25:17.511Z","updated_at":"2026-04-06T02:31:32.888Z","avatar_url":"https://github.com/mhogan-nwra.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"========\nenvector\n========\n\n\n    |pkg_img| |docs_img| |versions_img| |test_img| |downloads_img|\n\n\nThe envector library is a suite of tools written in Python to solve geographical position calculations. This is\nan open-source fork of the original nvector_ Python package based on the `MATLAB n-vector toolbox`_.\n\nExplanation of Intent\n=====================\n\nThis is a Python package that will assist you in calculating the distance between two points anywhere on, above, or\nbelow the Earth's surface. This can also be between two, three, or many points. This is quite useful in many areas from\nlogistics, tracking, navigation, data analytics, data science, and research. The calculations are simple and\nnon-singular. Full accuracy is achieved for any global position (and for any distance).\n\nUse Cases\n=========\n\nA use case in logistics is when you need to recommend to your customers the closest facilities or store\nlocations given an address or GPS coordinates. Your customers usually provide an address and you can convert that to GPS\ncoordinates, or geographic location in latitude and longitude. Given this information, you need to recommend the closest\nlocations and approximate distance in kilometers (km) or miles. You can implement the Haversine formula, which is a\nreasonable estimate if you are concerned with relatively short distances less than 100 km. However, you might meed to be\naware of the difference in altitudes between two locations. On top of all that, the Haversine formula is not accurate\nfor longer distances as the Earth is not exactly a sphere. You can properly account for all these issues using our\nenvector_ package.\n\nAnother use case is for navigation and tracking. Imagine that you\nhave a vehicle like a ship, airplane, or off-road vehicle on a fixed course. The vehicle has an unreliable and\ninaccurate GPS unit, and it is your job to ensure that the vehicle stays on course. This makes your job much harder if\nyou want to minimize the trip duration and vehicle fuel to maximize the number of trips possible for the day.\nFortunately, the envector_ package can help you 1) aggregate measurements to estimate the mean position, 2) interpolate\nthe next expected position in a fixed time interval, and 3) determine if the vehicle is veering off-course by measuring\nthe cross-track distance from the intended path.\n\nThese use cases and more are well supported by the envector_ package. We encourage you to check out the\nexamples below to help you maximize the utility of envector_.\n\nQuestions and Answers\n=====================\n\nIf you are coming from the nvector_ package, these Q-and-A can quickly explain this package.\n\n1. *What is the difference between this package and nvector*?\n\n    * Virtually none! The envector_ package is a fork of nvector_ with mostly aesthetic changes.\n    * No methods and functions have been removed, but documented deprecated methods in nvector_ will be removed.\n    * If your Python software worked with nvector_, then there is a good chance envector_ will also work. The caveats\n      are that this package abandons Python2 and extends to Python3.9+ support.\n\n2. *Why did you call this package \"envector\"*?\n\n    * The name honors the original nvector_ Python package and the progenitor `MATLAB n-vector toolbox`_. There are\n      adaptations in other languages as noted in the `nvector downloads`_ page.\n    * The names nvector_ and envector_ are homophones (pronounced the same), so the name invokes the original n-vector\n      origin.\n\n3. *Why did you fork nvector*?\n\n    * Primarily because the nvector_ Python package is broken with NumPy version 2.\n    * There is no indication that the situation will change.\n\n4. *What changes are there with from nvector*?\n\n    * The major difference is the namespace. Any place where your project have statements like:\n\n       .. code-block:: python\n            :caption: Importing the nvector package\n\n            import nvector as nv\n            from nvector import GeoPoint\n\n      You would replace them:\n\n        .. code-block:: python\n            :caption: Importing the envector package instead\n\n            import envector as nv\n            from envector import GeoPoint\n\n    * The envector_ package is a Python3-only package as it embraces static typing in most cases.\n    * Documentation is expanded in some cases.\n    * The docstrings have been refactored to utilize the Napoleon docstring style.\n\n5. *When is the appropriate to switch to envector*?\n\n    * If your Python software must support NumPy version 2,\n    * If your Python software also stops supporting Python versions after its end-of-life cycle.\n\n6. *How do I make the switch to envector*?\n\n    * If your project utilizes CPython3.9 through 3.12, inclusive, then you can simply change your `requirements.txt`,\n      `environment.yml`, `pyproject.toml`, or `setup.py` file to specify envector_.\n\n        .. code-block:: text\n            :caption: `requirements.txt` format\n\n            # requirements.txt format\n            envector\u003e=0\n\n        .. code-block:: yaml\n            :caption: Anaconda `environment.yml` format\n\n            # environment.yml format\n            - pip:\n              - envector\u003e=0\n\n        .. code-block:: toml\n            :caption: `pyproject.toml` format\n\n            # pyproject.toml format\n            # PEP 508 compliant\n            [project]\n            dependencies = [\n                \"envector\u003e=0\"\n            ]\n\n            # Poetry (not PEP 508 compliant)\n            [tool.poetry.dependencies]\n            envector = \"\u003e=0\"\n\n        .. code-block:: python\n            :caption: `setup.py` format\n\n            # setup.py format\n            install_requires=['envector\u003e=0',\n                              ...\n                              ]\n\n        * Your Python code will now need to import envector_\n\n    * If your project uses anything less than CPython3.9, then it depends on how your project is specified. If you are\n      using `pyproject.toml` or `setup.py`, then the changes are relatively simple as shown below. The other common\n      Anaconda `environment.yml` and `requirements.txt` formats require you to pick one depending on the Python\n      version. For Python2 to 3.8, you cannot use envector_.\n\n        .. code-block:: toml\n            :caption: `pyproject.toml` format to specify both nvector and envector\n\n            # pyproject.toml format\n            # PEP 508 compliant\n            [project]\n            dependencies = [\n                \"envector\u003e=0; python_version \u003e= '3.9'\",\n                \"nvector\u003e=0; python_version \u003c '3.9'\",\n            ]\n\n            # Poetry (not PEP 508 compliant)\n            [tool.poetry.dependencies]\n            envector = { version = \"\u003e=0\", python = \"\u003e=3.9\" }\n            nvector = { version = \"\u003e=0\", python = \"\u003c3.9\" }\n\n        .. code-block:: python\n            :caption: `setup.py` format to specify both nvector and envector\n\n            # setup.py format\n            install_requires=['envector\u003e=0; python_version \u003e= \"3.9\"',\n                              'nvector\u003e=0; python_version \u003c \"3.9\"',\n                              ...\n                              ]\n\n        * Your Python code will now need to try and import envector_ or nvector_ in a try-except block.\n\n            .. code-block:: python\n                :caption: Code block to import either nvector or envector\n\n                    # Code block to import either nvector or envector\n                    try:\n                        import nvector as nv\n                    except (ImportError,):\n                        import envector as nv\n\n\nTechnical Description\n=====================\n\nIn this library, we represent position with an \"n-vector\",  which\nis the normal vector to the Earth model (the same reference ellipsoid that is\nused for latitude and longitude). When using n-vector, all Earth-positions are\ntreated equally, and there is no need to worry about singularities or\ndiscontinuities. An additional benefit with using n-vector is that many\nposition calculations can be solved with simple vector algebra\n(e.g. dot product and cross product).\n\nConverting between n-vector and latitude/longitude is unambiguous and easy\nusing the provided functions.\n\nn_E is n-vector in the program code, while in documents we use nE. E denotes\nan Earth-fixed coordinate frame, and it indicates that the three components of\nn-vector are along the three axes of E. More details about the notation and\nreference frames can be found in the `documentation. \n\u003chttps://www.navlab.net/nvector/#vector_symbols\u003e`_\n\n\nDocumentation and code\n======================\n\nOfficial documentation:\n\nhttp://www.navlab.net/nvector/\n\nhttp://envector.readthedocs.io/en/latest/\n\n*Kenneth Gade (2010):*\n    `A Nonsingular Horizontal Position Representation,\n    The Journal of Navigation, Volume 63, Issue 03, pp 395-417, July 2010.\n    \u003chttp://www.navlab.net/Publications/A_Nonsingular_Horizontal_Position_Representation.pdf\u003e`_\n\n\nBleeding edge: https://github.com/mhogan-nwra/envector.\n\nOfficial releases available at: http://pypi.python.org/pypi/envector.\n\nOriginal/precursor package nvector_ at:  http://pypi.python.org/pypi/nvector.\n\n\nInstall envector\n================\n\nIf you have pip installed and are online, then simply type:\n\n    $ pip install envector\n\nto get the latest stable version. Using pip also has the advantage that all\nrequirements are automatically installed.\n\nYou can download nvector and all dependencies to a folder \"pkg\", by the following:\n\n   $ pip install --download=pkg envector\n\nTo install the downloaded envector, just type:\n\n   $ pip install --no-index --find-links=pkg envector\n\n\nVerifying installation\n======================\nTo verify that envector can be seen by Python, type ``python`` from your shell.\nThen at the Python prompt, try to import envector:\n\n.. parsed-literal::\n\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e print(nv.__version__)\n    0.3.1\n\n\nTo test if the toolbox is working correctly paste the following in an interactive\npython session::\n\n   import envector as nv\n   nv.test('--doctest-modules')\n\n\n.. _examples:\n\nGetting Started with Examples\n=============================\n\nBelow the object-oriented solution to some common geodesic problems are given.\nIn the first example the functional solution is also given.\nThe functional solutions to the remaining problems can be found in\nthe functional examples section\nof the tutorial.\n\n\n**Example 1: \"A and B to delta\"**\n---------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex1img.png\n\n\nGiven two positions, A and B as latitudes, longitudes and depths relative to\nEarth, E.\n\nFind the exact vector between the two positions, given in meters north, east,\nand down, and find the direction (azimuth) to B, relative to north.\nAssume WGS-84 ellipsoid. The given depths are from the ellipsoid surface.\nUse position A to define north, east, and down directions.\n(Due to the curvature of Earth and different directions to the North Pole,\nthe north, east, and down directions will change (relative to Earth) for\ndifferent places. Position A must be outside the poles for the north and east\ndirections to be defined.)\n\nSolution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e wgs84 = nv.FrameE(name='WGS84')\n    \u003e\u003e\u003e pointA = wgs84.GeoPoint(latitude=1, longitude=2, z=3, degrees=True)\n    \u003e\u003e\u003e pointB = wgs84.GeoPoint(latitude=4, longitude=5, z=6, degrees=True)\n\nStep1:  Find p_AB_N (delta decomposed in N).\n    \u003e\u003e\u003e p_AB_N = pointA.delta_to(pointB)\n    \u003e\u003e\u003e x, y, z = p_AB_N.pvector.ravel()\n    \u003e\u003e\u003e 'Ex1: delta north, east, down = {0:8.2f}, {1:8.2f}, {2:8.2f}'.format(x, y, z)\n    'Ex1: delta north, east, down = 331730.23, 332997.87, 17404.27'\n\nStep2: Also find the direction (azimuth) to B, relative to north:\n    \u003e\u003e\u003e 'azimuth = {0:4.2f} deg'.format(p_AB_N.azimuth_deg)\n    'azimuth = 45.11 deg'\n    \u003e\u003e\u003e 'elevation = {0:4.2f} deg'.format(p_AB_N.elevation_deg)\n    'elevation = 2.12 deg'\n    \u003e\u003e\u003e 'distance = {0:4.2f} m'.format(p_AB_N.length)\n    'distance = 470356.72 m'\n\nFunctional Solution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e from envector import rad, deg\n\n    \u003e\u003e\u003e lat_EA, lon_EA, z_EA = rad(1), rad(2), 3\n    \u003e\u003e\u003e lat_EB, lon_EB, z_EB = rad(4), rad(5), 6\n\nStep1: Convert to n-vectors:\n    \u003e\u003e\u003e n_EA_E = nv.lat_lon2n_E(lat_EA, lon_EA)\n    \u003e\u003e\u003e n_EB_E = nv.lat_lon2n_E(lat_EB, lon_EB)\n\nStep2: Find p_AB_E (delta decomposed in E).WGS-84 ellipsoid is default:\n    \u003e\u003e\u003e p_AB_E = nv.n_EA_E_and_n_EB_E2p_AB_E(n_EA_E, n_EB_E, z_EA, z_EB)\n\nStep3: Find R_EN for position A:\n    \u003e\u003e\u003e R_EN = nv.n_E2R_EN(n_EA_E)\n\nStep4: Find p_AB_N (delta decomposed in N).\n    \u003e\u003e\u003e p_AB_N = np.dot(R_EN.T, p_AB_E).ravel()\n    \u003e\u003e\u003e x, y, z = p_AB_N\n    \u003e\u003e\u003e 'Ex1: delta north, east, down = {0:8.2f}, {1:8.2f}, {2:8.2f}'.format(x, y, z)\n    'Ex1: delta north, east, down = 331730.23, 332997.87, 17404.27'\n\nStep5: Also find the direction (azimuth) to B, relative to north:\n    \u003e\u003e\u003e azimuth = np.arctan2(y, x)\n    \u003e\u003e\u003e 'azimuth = {0:4.2f} deg'.format(deg(azimuth))\n    'azimuth = 45.11 deg'\n\n    \u003e\u003e\u003e distance = np.linalg.norm(p_AB_N)\n    \u003e\u003e\u003e elevation = np.arcsin(z / distance)\n    \u003e\u003e\u003e 'elevation = {0:4.2f} deg'.format(deg(elevation))\n    'elevation = 2.12 deg'\n\n    \u003e\u003e\u003e 'distance = {0:4.2f} m'.format(distance)\n    'distance = 470356.72 m'\n\nSee also\n    `Example 1 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_1\u003e`_\n\n\n**Example 2: \"B and delta to C\"**\n---------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex2img.png\n\nA radar or sonar attached to a vehicle B (Body coordinate frame) measures the\ndistance and direction to an object C. We assume that the distance and two\nangles (typically bearing and elevation relative to B) are already combined to\nthe vector p_BC_B (i.e. the vector from B to C, decomposed in B). The position\nof B is given as n_EB_E and z_EB, and the orientation (attitude) of B is given\nas R_NB (this rotation matrix can be found from roll/pitch/yaw by using zyx2R).\n\nFind the exact position of object C as n-vector and depth ( n_EC_E and z_EC ),\nassuming Earth ellipsoid with semi-major axis a and flattening f. For WGS-72,\nuse a = 6 378 135 m and f = 1/298.26.\n\n\nSolution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e wgs72 = nv.FrameE(name='WGS72')\n    \u003e\u003e\u003e wgs72 = nv.FrameE(a=6378135, f=1.0/298.26)\n\nStep 1: Position and orientation of B is given 400m above E:\n    \u003e\u003e\u003e n_EB_E = wgs72.Nvector(nv.unit([[1], [2], [3]]), z=-400)\n    \u003e\u003e\u003e frame_B = nv.FrameB(n_EB_E, yaw=10, pitch=20, roll=30, degrees=True)\n\nStep 2: Delta BC decomposed in B\n    \u003e\u003e\u003e p_BC_B = frame_B.Pvector(np.r_[3000, 2000, 100].reshape((-1, 1)))\n\nStep 3: Decompose delta BC in E\n    \u003e\u003e\u003e p_BC_E = p_BC_B.to_ecef_vector()\n\nStep 4: Find point C by adding delta BC to EB\n    \u003e\u003e\u003e p_EB_E = n_EB_E.to_ecef_vector()\n    \u003e\u003e\u003e p_EC_E = p_EB_E + p_BC_E\n    \u003e\u003e\u003e pointC = p_EC_E.to_geo_point()\n\n    \u003e\u003e\u003e lat, lon, z = pointC.latlon_deg\n    \u003e\u003e\u003e msg = 'Ex2: PosC: lat, lon = {:4.4f}, {:4.4f} deg,  height = {:4.2f} m'\n    \u003e\u003e\u003e msg.format(lat, lon, -z)\n    'Ex2: PosC: lat, lon = 53.3264, 63.4681 deg,  height = 406.01 m'\n\nSee also\n    `Example 2 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_2\u003e`_\n\n\n**Example 3: \"ECEF-vector to geodetic latitude\"**\n-------------------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex3img.png\n\n\nPosition B is given as an \"ECEF-vector\" p_EB_E (i.e. a vector from E, the\ncenter of the Earth, to B, decomposed in E).\nFind the geodetic latitude, longitude and height (latEB, lonEB and hEB),\nassuming WGS-84 ellipsoid.\n\n\nSolution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e wgs84 = nv.FrameE(name='WGS84')\n    \u003e\u003e\u003e position_B = 6371e3 * np.vstack((0.9, -1, 1.1))  # m\n    \u003e\u003e\u003e p_EB_E = wgs84.ECEFvector(position_B)\n    \u003e\u003e\u003e pointB = p_EB_E.to_geo_point()\n\n    \u003e\u003e\u003e lat, lon, z = pointB.latlon_deg\n    \u003e\u003e\u003e 'Ex3: Pos B: lat, lon = {:4.4f}, {:4.4f} deg, height = {:9.3f} m'.format(lat, lon, -z)\n    'Ex3: Pos B: lat, lon = 39.3787, -48.0128 deg, height = 4702059.834 m'\n\nSee also\n    `Example 3 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_3\u003e`_\n\n\n**Example 4: \"Geodetic latitude to ECEF-vector\"**\n-------------------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex4img.png\n\n\nGeodetic latitude, longitude and height are given for position B as latEB,\nlonEB and hEB, find the ECEF-vector for this position, p_EB_E.\n\n\nSolution:\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e wgs84 = nv.FrameE(name='WGS84')\n    \u003e\u003e\u003e pointB = wgs84.GeoPoint(latitude=1, longitude=2, z=-3, degrees=True)\n    \u003e\u003e\u003e p_EB_E = pointB.to_ecef_vector()\n\n    \u003e\u003e\u003e 'Ex4: p_EB_E = {} m'.format(p_EB_E.pvector.ravel().tolist())\n    'Ex4: p_EB_E = [6373290.277218279, 222560.20067473652, 110568.82718178593] m'\n\nSee also\n    `Example 4 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_4\u003e`_\n\n\n**Example 5: \"Surface distance\"**\n---------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex5img.png\n\n\nFind the surface distance sAB (i.e. great circle distance) between two\npositions A and B. The heights of A and B are ignored, i.e. if they don't have\nzero height, we seek the distance between the points that are at the surface of\nthe Earth, directly above/below A and B. The Euclidean distance (chord length)\ndAB should also be found. Use Earth radius 6371e3 m.\nCompare the results with exact calculations for the WGS-84 ellipsoid.\n\n\nSolution for a sphere:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e frame_E = nv.FrameE(a=6371e3, f=0)\n    \u003e\u003e\u003e positionA = frame_E.GeoPoint(latitude=88, longitude=0, degrees=True)\n    \u003e\u003e\u003e positionB = frame_E.GeoPoint(latitude=89, longitude=-170, degrees=True)\n\n    \u003e\u003e\u003e s_AB, azia, azib = positionA.distance_and_azimuth(positionB)\n    \u003e\u003e\u003e p_AB_E = positionB.to_ecef_vector() - positionA.to_ecef_vector()\n    \u003e\u003e\u003e d_AB = p_AB_E.length\n\n    \u003e\u003e\u003e msg = 'Ex5: Great circle and Euclidean distance = {}'\n    \u003e\u003e\u003e msg = msg.format('{:5.2f} km, {:5.2f} km')\n    \u003e\u003e\u003e msg.format(s_AB / 1000, d_AB / 1000)\n    'Ex5: Great circle and Euclidean distance = 332.46 km, 332.42 km'\n\nAlternative sphere solution:\n    \u003e\u003e\u003e path = nv.GeoPath(positionA, positionB)\n    \u003e\u003e\u003e s_AB2 = path.track_distance(method='greatcircle')\n    \u003e\u003e\u003e d_AB2 = path.track_distance(method='euclidean')\n    \u003e\u003e\u003e msg.format(s_AB2 / 1000, d_AB2 / 1000)\n    'Ex5: Great circle and Euclidean distance = 332.46 km, 332.42 km'\n\nExact solution for the WGS84 ellipsoid:\n    \u003e\u003e\u003e wgs84 = nv.FrameE(name='WGS84')\n    \u003e\u003e\u003e point1 = wgs84.GeoPoint(latitude=88, longitude=0, degrees=True)\n    \u003e\u003e\u003e point2 = wgs84.GeoPoint(latitude=89, longitude=-170, degrees=True)\n    \u003e\u003e\u003e s_12, azi1, azi2 = point1.distance_and_azimuth(point2)\n\n    \u003e\u003e\u003e p_12_E = point2.to_ecef_vector() - point1.to_ecef_vector()\n    \u003e\u003e\u003e d_12 = p_12_E.length\n    \u003e\u003e\u003e msg = 'Ellipsoidal and Euclidean distance = {:5.2f} km, {:5.2f} km'\n    \u003e\u003e\u003e msg.format(s_12 / 1000, d_12 / 1000)\n    'Ellipsoidal and Euclidean distance = 333.95 km, 333.91 km'\n\nSee also\n    `Example 5 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_5\u003e`_\n\n\n**Example 6 \"Interpolated position\"**\n-------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex6img.png\n\n\nGiven the position of B at time t0 and t1, n_EB_E(t0) and n_EB_E(t1).\n\nFind an interpolated position at time ti, n_EB_E(ti). All positions are given\nas n-vectors.\n\n\nSolution:\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e wgs84 = nv.FrameE(name='WGS84')\n    \u003e\u003e\u003e n_EB_E_t0 = wgs84.GeoPoint(89, 0, degrees=True).to_nvector()\n    \u003e\u003e\u003e n_EB_E_t1 = wgs84.GeoPoint(89, 180, degrees=True).to_nvector()\n    \u003e\u003e\u003e path = nv.GeoPath(n_EB_E_t0, n_EB_E_t1)\n\n    \u003e\u003e\u003e t0 = 10.\n    \u003e\u003e\u003e t1 = 20.\n    \u003e\u003e\u003e ti = 16.  # time of interpolation\n    \u003e\u003e\u003e ti_n = (ti - t0) / (t1 - t0) # normalized time of interpolation\n\n    \u003e\u003e\u003e g_EB_E_ti = path.interpolate(ti_n).to_geo_point()\n\n    \u003e\u003e\u003e lat_ti, lon_ti, z_ti = g_EB_E_ti.latlon_deg\n    \u003e\u003e\u003e msg = 'Ex6, Interpolated position: lat, lon = {:2.1f} deg, {:2.1f} deg'\n    \u003e\u003e\u003e msg.format(lat_ti, lon_ti)\n    'Ex6, Interpolated position: lat, lon = 89.8 deg, 180.0 deg'\n\nVectorized solution:\n    \u003e\u003e\u003e t = np.array([10, 20])\n    \u003e\u003e\u003e nvectors = wgs84.GeoPoint([89, 89], [0, 180], degrees=True).to_nvector()\n    \u003e\u003e\u003e nvectors_i = nvectors.interpolate(ti, t, kind='linear')\n    \u003e\u003e\u003e lati, loni, zi = nvectors_i.to_geo_point().latlon_deg\n    \u003e\u003e\u003e msg.format(lat_ti, lon_ti)\n    'Ex6, Interpolated position: lat, lon = 89.8 deg, 180.0 deg'\n\nSee also\n    `Example 6 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_6\u003e`_\n\n\n**Example 7: \"Mean position\"**\n------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex7img.png\n\n\nThree positions A, B, and C are given as n-vectors n_EA_E, n_EB_E, and n_EC_E.\nFind the mean position, M, given as n_EM_E.\nNote that the calculation is independent of the depths of the positions.\n\n\nSolution:\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e points = nv.GeoPoint(latitude=[90, 60, 50],\n    ...                      longitude=[0, 10, -20], degrees=True)\n    \u003e\u003e\u003e nvectors = points.to_nvector()\n    \u003e\u003e\u003e n_EM_E = nvectors.mean()\n    \u003e\u003e\u003e g_EM_E = n_EM_E.to_geo_point()\n    \u003e\u003e\u003e lat, lon = g_EM_E.latitude_deg, g_EM_E.longitude_deg\n    \u003e\u003e\u003e msg = 'Ex7: Pos M: lat, lon = {:4.4f}, {:4.4f} deg'\n    \u003e\u003e\u003e msg.format(lat, lon)\n    'Ex7: Pos M: lat, lon = 67.2362, -6.9175 deg'\n\nSee also\n    `Example 7 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_7\u003e`_\n\n\n**Example 8: \"A and azimuth/distance to B\"**\n--------------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex8img.png\n\n\nWe have an initial position A, direction of travel given as an azimuth\n(bearing) relative to north (clockwise), and finally the\ndistance to travel along a great circle given as sAB.\nUse Earth radius 6371e3 m to find the destination point B.\n\nIn geodesy this is known as \"The first geodetic problem\" or\n\"The direct geodetic problem\" for a sphere, and we see that this is similar to\n`Example 2 \u003chttp://www.navlab.net/nvector/#example_2\u003e`_, but now the delta is\ngiven as an azimuth and a great circle distance. (\"The second/inverse geodetic\nproblem\" for a sphere is already solved in Examples\n`1 \u003chttp://www.navlab.net/nvector/#example_1\u003e`_ and\n`5 \u003chttp://www.navlab.net/nvector/#example_5\u003e`_.)\n\n\nExact solution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e frame = nv.FrameE(a=6371e3, f=0)\n    \u003e\u003e\u003e pointA = frame.GeoPoint(latitude=80, longitude=-90, degrees=True)\n    \u003e\u003e\u003e pointB, azimuthb = pointA.displace(distance=1000, azimuth=200, degrees=True)\n    \u003e\u003e\u003e lat, lon = pointB.latitude_deg, pointB.longitude_deg\n\n    \u003e\u003e\u003e msg = 'Ex8, Destination: lat, lon = {:4.4f} deg, {:4.4f} deg'\n    \u003e\u003e\u003e msg.format(lat, lon)\n    'Ex8, Destination: lat, lon = 79.9915 deg, -90.0177 deg'\n\n    \u003e\u003e\u003e np.allclose(azimuthb, -160.01742926820506)\n    True\n\nGreatcircle solution:\n    \u003e\u003e\u003e pointB2, azimuthb = pointA.displace(distance=1000,\n    ...                                     azimuth=200,\n    ...                                     degrees=True,\n    ...                                     method='greatcircle')\n    \u003e\u003e\u003e lat2, lon2 = pointB2.latitude_deg, pointB.longitude_deg\n    \u003e\u003e\u003e msg.format(lat2, lon2)\n    'Ex8, Destination: lat, lon = 79.9915 deg, -90.0177 deg'\n\n    \u003e\u003e\u003e np.allclose(azimuthb, -160.0174292682187)\n    True\n\nSee also\n    `Example 8 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_8\u003e`_\n\n\n**Example 9: \"Intersection of two paths\"**\n------------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex9img.png\n\n\nDefine a path from two given positions (at the surface of a spherical Earth),\nas the great circle that goes through the two points.\n\nPath A is given by A1 and A2, while path B is given by B1 and B2.\n\nFind the position C where the two great circles intersect.\n\n\nSolution:\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e pointA1 = nv.GeoPoint(10, 20, degrees=True)\n    \u003e\u003e\u003e pointA2 = nv.GeoPoint(30, 40, degrees=True)\n    \u003e\u003e\u003e pointB1 = nv.GeoPoint(50, 60, degrees=True)\n    \u003e\u003e\u003e pointB2 = nv.GeoPoint(70, 80, degrees=True)\n    \u003e\u003e\u003e pathA = nv.GeoPath(pointA1, pointA2)\n    \u003e\u003e\u003e pathB = nv.GeoPath(pointB1, pointB2)\n\n    \u003e\u003e\u003e pointC = pathA.intersect(pathB)\n    \u003e\u003e\u003e pointC = pointC.to_geo_point()\n    \u003e\u003e\u003e lat, lon = pointC.latitude_deg, pointC.longitude_deg\n    \u003e\u003e\u003e msg = 'Ex9, Intersection: lat, lon = {:4.4f}, {:4.4f} deg'\n    \u003e\u003e\u003e msg.format(lat, lon)\n    'Ex9, Intersection: lat, lon = 40.3186, 55.9019 deg'\n\nCheck that PointC is not between A1 and A2 or B1 and B2:\n    \u003e\u003e\u003e pathA.on_path(pointC)\n    False\n    \u003e\u003e\u003e pathB.on_path(pointC)\n    False\n\nCheck that PointC is on the great circle going through path A and path B:\n    \u003e\u003e\u003e pathA.on_great_circle(pointC)\n    True\n    \u003e\u003e\u003e pathB.on_great_circle(pointC)\n    True\n\nSee also\n    `Example 9 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_9\u003e`_\n\n\n**Example 10: \"Cross track distance\"**\n--------------------------------------\n\n.. image:: https://raw.githubusercontent.com/mhogan-nwra/envector/master/docs/tutorials/images/ex10img.png\n\n\nPath A is given by the two positions A1 and A2 (similar to the previous\nexample).\n\nFind the cross track distance sxt between the path A (i.e. the great circle\nthrough A1 and A2) and the position B (i.e. the shortest distance at the\nsurface, between the great circle and B).\n\nAlso find the Euclidean distance dxt between B and the plane defined by the\ngreat circle. Use Earth radius 6371e3.\n\nFinally, find the intersection point on the great circle and determine if it is\nbetween position A1 and A2.\n\n\nSolution:\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e import envector as nv\n    \u003e\u003e\u003e frame = nv.FrameE(a=6371e3, f=0)\n    \u003e\u003e\u003e pointA1 = frame.GeoPoint(0, 0, degrees=True)\n    \u003e\u003e\u003e pointA2 = frame.GeoPoint(10, 0, degrees=True)\n    \u003e\u003e\u003e pointB = frame.GeoPoint(1, 0.1, degrees=True)\n    \u003e\u003e\u003e pathA = nv.GeoPath(pointA1, pointA2)\n\n    \u003e\u003e\u003e s_xt = pathA.cross_track_distance(pointB, method='greatcircle')\n    \u003e\u003e\u003e d_xt = pathA.cross_track_distance(pointB, method='euclidean')\n\n    \u003e\u003e\u003e val_txt = '{:4.2f} km, {:4.2f} km'.format(s_xt/1000, d_xt/1000)\n    \u003e\u003e\u003e 'Ex10: Cross track distance: s_xt, d_xt = {}'.format(val_txt)\n    'Ex10: Cross track distance: s_xt, d_xt = 11.12 km, 11.12 km'\n\n    \u003e\u003e\u003e pointC = pathA.closest_point_on_great_circle(pointB)\n    \u003e\u003e\u003e np.allclose(pathA.on_path(pointC), True)\n    True\n\nSee also\n    `Example 10 at www.navlab.net \u003chttp://www.navlab.net/nvector/#example_10\u003e`_\n\n\n\nAcknowledgements\n================\n\nThe `nvector package \u003chttp://pypi.python.org/pypi/nvector/\u003e`_ for\n`Python \u003chttps://www.python.org/\u003e`_ was written by Per A. Brodtkorb at\n`FFI (The Norwegian Defence Research Establishment) \u003chttp://www.ffi.no/en\u003e`_\nbased on the `nvector toolbox \u003chttp://www.navlab.net/nvector/#download\u003e`_ for\n`Matlab \u003chttp://www.mathworks.com\u003e`_ written by the navigation group at\n`FFI \u003chttp://www.ffi.no/en\u003e`_. The nvector.core and nvector.rotation module is a\nvectorized reimplementation of the matlab nvector toolbox while the nvector.objects\nmodule is a new easy to use object oriented user interface to the nvector core\nfunctionality documented in [GB20]_.\n\nMost of the content is based on the article by K. Gade [Gad10]_.\n\nThus this article should be cited in publications using this page or\ndownloaded program code.\n\nHowever, if you use any of the FrameE.direct, FrameE.inverse,\nGeoPoint.distance_and_azimuth or GeoPoint.displace methods you should also cite\nthe article by Karney [Kar13]_ because these methods call\nKarney's `geographiclib \u003chttps://pypi.python.org/pypi/geographiclib\u003e`_ library\nto do the calculations.\n\n\n.. _nvector: https://github.com/pbrod/nvector\n.. _envector: https://github.com/mhogan-nwra/envector\n.. _nvector downloads: https://www.ffi.no/en/research/n-vector/n-vector-downloads\n.. _MATLAB n-vector toolbox: https://github.com/FFI-no/n-vector\n.. |pkg_img| image:: https://badge.fury.io/py/envector.svg\n   :target: https://badge.fury.io/py/envector\n.. |docs_img| image:: https://readthedocs.org/projects/pip/badge/?version=stable\n   :target: http://envector.readthedocs.org/en/stable/\n.. |versions_img| image:: https://img.shields.io/pypi/pyversions/envector.svg\n   :target: https://github.com/mhogan-nwra/envector\n.. |test_img| image:: https://github.com/mhogan-nwra/envector/actions/workflows/python-package.yml/badge.svg\n   :target: https://github.com/mhogan-nwra/envector/actions/workflows/python-package.yml\n.. |downloads_img| image:: https://pepy.tech/badge/envector/month\n   :target: https://pepy.tech/project/envector\n   :alt: PyPI - Downloads\n\n\nReferences\n==========\n\n.. [Gad10] K. Gade, `A Nonsingular Horizontal Position Representation, J. Navigation, 63(3):395-417, 2010.\n           \u003chttp://www.navlab.net/Publications/A_Nonsingular_Horizontal_Position_Representation.pdf\u003e`_\n.. [Kar13] C.F.F. Karney. `Algorithms for geodesics. J. Geodesy, 87(1):43-55, 2013. \u003chttps://rdcu.be/cccgm\u003e`_\n\n.. [GB20] K. Gade and P.A. Brodtkorb, `Nvector Documentation for Python, 2020.\n           \u003chttps://nvector.readthedocs.io/en/v0.7.6\u003e`_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhogan-nwra%2Fenvector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhogan-nwra%2Fenvector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhogan-nwra%2Fenvector/lists"}