pygeofun


Namepygeofun JSON
Version 0.0.14 PyPI version JSON
download
home_pagehttps://github.com/jrversteegh/geofun
SummaryGeographic Functions: geodesics and rhumblines, orthodromes and loxodromes
upload_time2024-03-23 17:22:51
maintainerNone
docs_urlNone
authorJaap Versteegh
requires_python<4.0,>=3.9
licenseNone
keywords geodesic rhumb line loxodrome orthodrome distance azimuth
VCS
bugtrack_url
requirements wheel setuptools cmake pybind11 tomli
Travis-CI No Travis.
coveralls test coverage No coveralls.
            GeoFun
======

Library for doing geographic calculations like distance, azimuth and
position determination for geodesics and rhumb lines, orthodromes and
loxodromes, respectively.

This version makes use of GeographicLib for doing most of the
calculations.

This is a C++ package that uses pybind11 to wrap the C++ version of
GeographicLib, which makes it faster (~100x) than the pure python
version of
`geographiclib <https://geographiclib.sourceforge.io/html/python/index.html>`__.

Compare:

.. code:: python

   In [1]: from geofun import geodesic_inverse

   In [2]: %timeit geodesic_inverse(52, 4, 28, -16.6)
   1.17 µs ± 37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

   In [3]: from geographiclib.geodesic import Geodesic

   In [4]: %timeit Geodesic.WGS84.Inverse(52, 4, 28, -16.6)
   107 µs ± 170 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

   In [5]: geodesic_inverse(52, 4, 28, -16.6)
   Out[5]: (-139.28471885516532, 3168557.154495447, -152.90624110350674)

   In [6]: Geodesic.WGS84.Inverse(52, 4, 28, -16.6)
   Out[6]:
   {'lat1': 52,
    'lon1': 4.0,
    'lat2': 28,
    'lon2': -16.6,
    'a12': 28.519118381735783,
    's12': 3168557.1544954455,
    'azi1': -139.28471885516532,
    'azi2': -152.90624110350674}


Installing
----------

``pip install pygeofun`` should work without needing to compile anything on Windows, Linux
(x86_64, aarch64) and MacOS 13 (x86_64) for python versions 3.9 - 3.12. For other
platforms you might need to build the C++ parts.
Wheel contributions for other platforms are very welcome.


Building
--------

-  Get
   `poetry <https://python-poetry.org/docs/master/#installing-with-the-official-installer>`__
   if you don't have it

-  Check out the source code:
   ``git clone https://github.com/jrversteegh/geofun.git --recurse-submodules``

-  Execute ``poetry build`` to build the package or ``poetry install``
   to get a virtual environment to work in. Both require a working
   modern C++ compiler. GCC 9.4 and MSVC 14.3 were tested. Others may
   work.

Examples
--------

Some operator abuse was used to mark the difference between geodesic and
mercator based operations. ``+`` and ``-`` are addition and subtraction
in the mercator projection (loxodromes) and ``*`` and ``/`` are addition
and subtraction on geodesics (orthodromes). If you object to this,
you’re probably right. Any suggestions for a better way are quite
welcome.

.. code:: python

   from geofun import Position, Vector

   # Just off Hoek van Holland
   org = Position(52.0, 4.0)
   nm95 = 95 * 1852.0

   # Go west 95 nm to Felixstowe
   rmbv = Vector(270.0, nm95)
   pos1 = org + rmbv

   # Go to the same point using great circle line
   gcv = pos1 / org
   pos2 = org * gcv

   # We should end up at the same location
   assert pos1 == pos2

   # How disappointing: we managed to gain just 9m by crossing the
   # North sea using a great circle :p
   assert nm95 - gcv.length == 9.101067085022805, f'Unexpected: {gcv.length}'

   print(f'From {org} to {pos1}')
   print(f'Rhumb: {rmbv}')
   print(f'Great circle: {gcv}')

   # Another verification
   assert pos1 - org == rmbv
   assert pos1 / org == gcv


Another example. Flying from Kennedy Airport to Amsterdam Schiphol Airport and splitting
both a great circle and a rhumbline route into segments:

.. code:: python

   from geofun import Position, Vector

   # Both airports
   JFK = Position("40°38′23″N 73°46′44″W")
   AMS = Position("52°18′00″N 4°45′54″E")

   # Loxodromic route:
   loxo = (AMS - JFK).split_loxo(JFK, 10)
   # Print list of positions and flight vectors
   print("\nLoxodrome JFK -> AMS:")
   for p1, p2 in zip(loxo[:-1], loxo[1:]):
     print(f"Position: {p1}, vector: {p2 - p1}")
   print(f"Destination: {p2}")

   # Orthodromic route:
   ortho = (AMS / JFK).split_ortho(JFK, 10)
   # Print list of positions and flight vectors
   print("\nOrthodrome JFK -> AMS:")
   for p1, p2 in zip(ortho[:-1], ortho[1:]):
     print(f"Position: {p1}, vector: {p2 / p1}")
   print(f"Destination: {p2}")


Classes
-------

**Position**
  - latitude
  - longitude

``Position(latitude: int, longitude: int) -> Position`` Position in arc seconds.

``Position(latitude: float, longitude: float) -> Position`` Position in arc degrees.

``Position(position: str) -> Position`` Position parsed from string.

**Vector**
  - azimuth 
  - length

``Vector(azimuth: float, length: float) -> Vector`` Polar vector in arc degrees and meters.

**Point**
  - x 
  - y

``Point(x: float, y: float) -> Point`` Point on locally flat coordinate system, x pointing north, y pointing east.

Many operators will work on classes like:

- *Point* + *Point*, adds x and y coordinates of points
- *Point* + *Vector*, offsets point by vector
- *Position* + *Vector*, offsets position by vector along loxodrome
- *Position* * *Vector*, offsets position by vector along orthodrome
- *Position* - *Position*, get loxodromic vector from position to position
- *Position* / *Position*, get orthodromic vector from position to position

Functions
---------

``get_version() -> str``

Get the library version

``geodesic_direct(latitude: float, longitude: float, azimuth: float, distance: float) -> tuple``

Get position and final azimuth after moving distance along great circle
with starting azimuth

``geodesic_inverse(latitude1: float, longitude1: float, latitude2: float, longitude2: float) -> tuple``

Get starting azimuth, distance and ending azimuth of great circle
between positions

``rhumb_direct(latitude: float, longitude: float, azimuth: float, distance: float) -> tuple``

Get position and final azimuth after moving distance from starting
position at fixed azimuth/along rhumb line

``rhumb_inverse(latitude1: float, longitude1: float, latitude2: float, longitude2: float) -> tuple``

Get rhumb line azimuth, distance and final azimuth between positions

``angle_diff(arg0: numpy.ndarray[numpy.float64], arg1: numpy.ndarray[numpy.float64]) -> object``

Signed difference between to angles

``angle_mod(arg0: numpy.ndarray[numpy.float64]) -> object``

Return angle bound to [0.0, 360.0>

``angle_mod_signed(arg0: numpy.ndarray[numpy.float64]) -> object``

Return angle bound to [-180.0, 180.0>

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jrversteegh/geofun",
    "name": "pygeofun",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.9",
    "maintainer_email": null,
    "keywords": "geodesic, rhumb line, loxodrome, orthodrome, distance, azimuth",
    "author": "Jaap Versteegh",
    "author_email": "j.r.versteegh@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/28/64/e4293802e3c13d243022e465e7f38b7483d544f03a0e43ce8778e567869f/pygeofun-0.0.14.tar.gz",
    "platform": null,
    "description": "GeoFun\n======\n\nLibrary for doing geographic calculations like distance, azimuth and\nposition determination for geodesics and rhumb lines, orthodromes and\nloxodromes, respectively.\n\nThis version makes use of GeographicLib for doing most of the\ncalculations.\n\nThis is a C++ package that uses pybind11 to wrap the C++ version of\nGeographicLib, which makes it faster (~100x) than the pure python\nversion of\n`geographiclib <https://geographiclib.sourceforge.io/html/python/index.html>`__.\n\nCompare:\n\n.. code:: python\n\n   In [1]: from geofun import geodesic_inverse\n\n   In [2]: %timeit geodesic_inverse(52, 4, 28, -16.6)\n   1.17 \u00b5s \u00b1 37 ns per loop (mean \u00b1 std. dev. of 7 runs, 1000000 loops each)\n\n   In [3]: from geographiclib.geodesic import Geodesic\n\n   In [4]: %timeit Geodesic.WGS84.Inverse(52, 4, 28, -16.6)\n   107 \u00b5s \u00b1 170 ns per loop (mean \u00b1 std. dev. of 7 runs, 10000 loops each)\n\n   In [5]: geodesic_inverse(52, 4, 28, -16.6)\n   Out[5]: (-139.28471885516532, 3168557.154495447, -152.90624110350674)\n\n   In [6]: Geodesic.WGS84.Inverse(52, 4, 28, -16.6)\n   Out[6]:\n   {'lat1': 52,\n    'lon1': 4.0,\n    'lat2': 28,\n    'lon2': -16.6,\n    'a12': 28.519118381735783,\n    's12': 3168557.1544954455,\n    'azi1': -139.28471885516532,\n    'azi2': -152.90624110350674}\n\n\nInstalling\n----------\n\n``pip install pygeofun`` should work without needing to compile anything on Windows, Linux\n(x86_64, aarch64) and MacOS 13 (x86_64) for python versions 3.9 - 3.12. For other\nplatforms you might need to build the C++ parts.\nWheel contributions for other platforms are very welcome.\n\n\nBuilding\n--------\n\n-  Get\n   `poetry <https://python-poetry.org/docs/master/#installing-with-the-official-installer>`__\n   if you don't have it\n\n-  Check out the source code:\n   ``git clone https://github.com/jrversteegh/geofun.git --recurse-submodules``\n\n-  Execute ``poetry build`` to build the package or ``poetry install``\n   to get a virtual environment to work in. Both require a working\n   modern C++ compiler. GCC 9.4 and MSVC 14.3 were tested. Others may\n   work.\n\nExamples\n--------\n\nSome operator abuse was used to mark the difference between geodesic and\nmercator based operations. ``+`` and ``-`` are addition and subtraction\nin the mercator projection (loxodromes) and ``*`` and ``/`` are addition\nand subtraction on geodesics (orthodromes). If you object to this,\nyou\u2019re probably right. Any suggestions for a better way are quite\nwelcome.\n\n.. code:: python\n\n   from geofun import Position, Vector\n\n   # Just off Hoek van Holland\n   org = Position(52.0, 4.0)\n   nm95 = 95 * 1852.0\n\n   # Go west 95 nm to Felixstowe\n   rmbv = Vector(270.0, nm95)\n   pos1 = org + rmbv\n\n   # Go to the same point using great circle line\n   gcv = pos1 / org\n   pos2 = org * gcv\n\n   # We should end up at the same location\n   assert pos1 == pos2\n\n   # How disappointing: we managed to gain just 9m by crossing the\n   # North sea using a great circle :p\n   assert nm95 - gcv.length == 9.101067085022805, f'Unexpected: {gcv.length}'\n\n   print(f'From {org} to {pos1}')\n   print(f'Rhumb: {rmbv}')\n   print(f'Great circle: {gcv}')\n\n   # Another verification\n   assert pos1 - org == rmbv\n   assert pos1 / org == gcv\n\n\nAnother example. Flying from Kennedy Airport to Amsterdam Schiphol Airport and splitting\nboth a great circle and a rhumbline route into segments:\n\n.. code:: python\n\n   from geofun import Position, Vector\n\n   # Both airports\n   JFK = Position(\"40\u00b038\u203223\u2033N 73\u00b046\u203244\u2033W\")\n   AMS = Position(\"52\u00b018\u203200\u2033N 4\u00b045\u203254\u2033E\")\n\n   # Loxodromic route:\n   loxo = (AMS - JFK).split_loxo(JFK, 10)\n   # Print list of positions and flight vectors\n   print(\"\\nLoxodrome JFK -> AMS:\")\n   for p1, p2 in zip(loxo[:-1], loxo[1:]):\n     print(f\"Position: {p1}, vector: {p2 - p1}\")\n   print(f\"Destination: {p2}\")\n\n   # Orthodromic route:\n   ortho = (AMS / JFK).split_ortho(JFK, 10)\n   # Print list of positions and flight vectors\n   print(\"\\nOrthodrome JFK -> AMS:\")\n   for p1, p2 in zip(ortho[:-1], ortho[1:]):\n     print(f\"Position: {p1}, vector: {p2 / p1}\")\n   print(f\"Destination: {p2}\")\n\n\nClasses\n-------\n\n**Position**\n  - latitude\n  - longitude\n\n``Position(latitude: int, longitude: int) -> Position`` Position in arc seconds.\n\n``Position(latitude: float, longitude: float) -> Position`` Position in arc degrees.\n\n``Position(position: str) -> Position`` Position parsed from string.\n\n**Vector**\n  - azimuth \n  - length\n\n``Vector(azimuth: float, length: float) -> Vector`` Polar vector in arc degrees and meters.\n\n**Point**\n  - x \n  - y\n\n``Point(x: float, y: float) -> Point`` Point on locally flat coordinate system, x pointing north, y pointing east.\n\nMany operators will work on classes like:\n\n- *Point* + *Point*, adds x and y coordinates of points\n- *Point* + *Vector*, offsets point by vector\n- *Position* + *Vector*, offsets position by vector along loxodrome\n- *Position* * *Vector*, offsets position by vector along orthodrome\n- *Position* - *Position*, get loxodromic vector from position to position\n- *Position* / *Position*, get orthodromic vector from position to position\n\nFunctions\n---------\n\n``get_version() -> str``\n\nGet the library version\n\n``geodesic_direct(latitude: float, longitude: float, azimuth: float, distance: float) -> tuple``\n\nGet position and final azimuth after moving distance along great circle\nwith starting azimuth\n\n``geodesic_inverse(latitude1: float, longitude1: float, latitude2: float, longitude2: float) -> tuple``\n\nGet starting azimuth, distance and ending azimuth of great circle\nbetween positions\n\n``rhumb_direct(latitude: float, longitude: float, azimuth: float, distance: float) -> tuple``\n\nGet position and final azimuth after moving distance from starting\nposition at fixed azimuth/along rhumb line\n\n``rhumb_inverse(latitude1: float, longitude1: float, latitude2: float, longitude2: float) -> tuple``\n\nGet rhumb line azimuth, distance and final azimuth between positions\n\n``angle_diff(arg0: numpy.ndarray[numpy.float64], arg1: numpy.ndarray[numpy.float64]) -> object``\n\nSigned difference between to angles\n\n``angle_mod(arg0: numpy.ndarray[numpy.float64]) -> object``\n\nReturn angle bound to [0.0, 360.0>\n\n``angle_mod_signed(arg0: numpy.ndarray[numpy.float64]) -> object``\n\nReturn angle bound to [-180.0, 180.0>\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Geographic Functions: geodesics and rhumblines, orthodromes and loxodromes",
    "version": "0.0.14",
    "project_urls": {
        "Homepage": "https://github.com/jrversteegh/geofun",
        "Repository": "https://github.com/jrversteegh/geofun"
    },
    "split_keywords": [
        "geodesic",
        " rhumb line",
        " loxodrome",
        " orthodrome",
        " distance",
        " azimuth"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0de1a6a13ace712abadccd176c1df99a055c26ed499494c69de17cc106b60964",
                "md5": "318ec861553ef5f318a5d856b70b256b",
                "sha256": "ee135a596b4836f0ec793849e14ed71b7c79d50ef5e15bff2098ecfbb15b1d1c"
            },
            "downloads": -1,
            "filename": "pygeofun-0.0.14-cp310-cp310-manylinux_2_36_x86_64.whl",
            "has_sig": false,
            "md5_digest": "318ec861553ef5f318a5d856b70b256b",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": "<4.0,>=3.9",
            "size": 285055,
            "upload_time": "2024-03-23T17:22:49",
            "upload_time_iso_8601": "2024-03-23T17:22:49.006082Z",
            "url": "https://files.pythonhosted.org/packages/0d/e1/a6a13ace712abadccd176c1df99a055c26ed499494c69de17cc106b60964/pygeofun-0.0.14-cp310-cp310-manylinux_2_36_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9869413c95f9afc60ad86b0b816c1ffac9d07827ec2947005335f3e55667198d",
                "md5": "b55d826bb693c504ae35189c3845d523",
                "sha256": "1e4b34fe305a27ac74168ea6decdc793b6cc90f1b5c15e423d1cef685b4510fc"
            },
            "downloads": -1,
            "filename": "pygeofun-0.0.14-cp311-cp311-manylinux_2_36_x86_64.whl",
            "has_sig": false,
            "md5_digest": "b55d826bb693c504ae35189c3845d523",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": "<4.0,>=3.9",
            "size": 286400,
            "upload_time": "2024-03-23T17:22:49",
            "upload_time_iso_8601": "2024-03-23T17:22:49.353147Z",
            "url": "https://files.pythonhosted.org/packages/98/69/413c95f9afc60ad86b0b816c1ffac9d07827ec2947005335f3e55667198d/pygeofun-0.0.14-cp311-cp311-manylinux_2_36_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "821512affb0d8774b69fae6166d238335ebca337592327577597d065f0d1ba1f",
                "md5": "969a027dc3e570d7891e77950b013604",
                "sha256": "3e0990496b4ed1b383527bb59e2cd4cdfb7d6027fe7c1a095ac35913039c1705"
            },
            "downloads": -1,
            "filename": "pygeofun-0.0.14-cp312-cp312-manylinux_2_36_x86_64.whl",
            "has_sig": false,
            "md5_digest": "969a027dc3e570d7891e77950b013604",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": "<4.0,>=3.9",
            "size": 285327,
            "upload_time": "2024-03-23T17:22:51",
            "upload_time_iso_8601": "2024-03-23T17:22:51.532241Z",
            "url": "https://files.pythonhosted.org/packages/82/15/12affb0d8774b69fae6166d238335ebca337592327577597d065f0d1ba1f/pygeofun-0.0.14-cp312-cp312-manylinux_2_36_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bc68472630b73da45e122563257a88596b094bc106331754c3c786fa527d556b",
                "md5": "9bcb1b87e43a43ac111479bd02190ebc",
                "sha256": "7c3a7d20649b28cbf556cb07b06a927e94fd36649f466f6a8514be16d33d19fc"
            },
            "downloads": -1,
            "filename": "pygeofun-0.0.14-cp39-cp39-manylinux_2_36_x86_64.whl",
            "has_sig": false,
            "md5_digest": "9bcb1b87e43a43ac111479bd02190ebc",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": "<4.0,>=3.9",
            "size": 285042,
            "upload_time": "2024-03-23T17:22:51",
            "upload_time_iso_8601": "2024-03-23T17:22:51.895208Z",
            "url": "https://files.pythonhosted.org/packages/bc/68/472630b73da45e122563257a88596b094bc106331754c3c786fa527d556b/pygeofun-0.0.14-cp39-cp39-manylinux_2_36_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2864e4293802e3c13d243022e465e7f38b7483d544f03a0e43ce8778e567869f",
                "md5": "d4d758d0a9b7452311d4539c5cb4c684",
                "sha256": "8afb655f7a38c6ae36d6f4da8ea2b43e980e15714348c734ede12b24e1ff3bc1"
            },
            "downloads": -1,
            "filename": "pygeofun-0.0.14.tar.gz",
            "has_sig": false,
            "md5_digest": "d4d758d0a9b7452311d4539c5cb4c684",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.9",
            "size": 2503835,
            "upload_time": "2024-03-23T17:22:51",
            "upload_time_iso_8601": "2024-03-23T17:22:51.145867Z",
            "url": "https://files.pythonhosted.org/packages/28/64/e4293802e3c13d243022e465e7f38b7483d544f03a0e43ce8778e567869f/pygeofun-0.0.14.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-23 17:22:51",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jrversteegh",
    "github_project": "geofun",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "wheel",
            "specs": []
        },
        {
            "name": "setuptools",
            "specs": []
        },
        {
            "name": "cmake",
            "specs": []
        },
        {
            "name": "pybind11",
            "specs": []
        },
        {
            "name": "tomli",
            "specs": []
        }
    ],
    "lcname": "pygeofun"
}
        
Elapsed time: 0.20694s