{"id":19829754,"url":"https://github.com/gistrec/cpp-geometry-library","last_synced_at":"2025-09-20T01:08:31.125Z","repository":{"id":187165215,"uuid":"221438895","full_name":"gistrec/cpp-geometry-library","owner":"gistrec","description":"CPP Geometry Library provides utility functions for the computation of geometric data on the surface of the Earth.","archived":false,"fork":false,"pushed_at":"2020-02-16T12:29:47.000Z","size":62,"stargazers_count":31,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-08-09T08:14:20.320Z","etag":null,"topics":["cpp","distance","geometry-library","google-maps-api","latlng","polyline"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gistrec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-11-13T11:01:04.000Z","updated_at":"2023-08-09T08:14:27.840Z","dependencies_parsed_at":"2023-08-09T08:25:17.707Z","dependency_job_id":null,"html_url":"https://github.com/gistrec/cpp-geometry-library","commit_stats":null,"previous_names":["gistrec/cpp-geometry-library"],"tags_count":1,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gistrec%2Fcpp-geometry-library","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gistrec%2Fcpp-geometry-library/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gistrec%2Fcpp-geometry-library/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gistrec%2Fcpp-geometry-library/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gistrec","download_url":"https://codeload.github.com/gistrec/cpp-geometry-library/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224262990,"owners_count":17282457,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["cpp","distance","geometry-library","google-maps-api","latlng","polyline"],"created_at":"2024-11-12T11:19:52.619Z","updated_at":"2025-09-20T01:08:26.062Z","avatar_url":"https://github.com/gistrec.png","language":"C++","readme":"# Geometry Library\n\n\u003cp align=\"left\"\u003e\n    \u003ca href=\"https://circleci.com/gh/gistrec/cpp-geometry-library/tree/master\"\u003e\n        \u003cimg src=\"https://img.shields.io/circleci/build/github/gistrec/cpp-geometry-library/master\" alt=\"Build status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"#\"\u003e\n      \u003cimg src=\"https://img.shields.io/codacy/grade/bcff544711544d5fb7da95b68abf566d\" alt=\"Code quality\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/gistrec/cpp-geometry-library/releases\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/v/release/gistrec/cpp-geometry-library\" alt=\"Release\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"#\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/platform-windows%20%7C%20linux%20%7C%20osx-brightgreen\" alt=\"Supported platforms\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/gistrec/cpp-geometry-library/blob/master/LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/license/gistrec/cpp-geometry-library?color=brightgreen\" alt=\"License\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nC++ Geometry Library provides utility functions for the computation of geometric data on the surface of the Earth. Code ported from Google [Maps Android API](https://github.com/googlemaps/android-maps-utils/).\n\n## Features\n\n* [Spherical](https://developers.google.com/maps/documentation/javascript/reference#spherical) contains spherical geometry utilities allowing you to compute angles, distances and areas from latitudes and longitudes.\n* [Poly](https://developers.google.com/maps/documentation/javascript/reference#poly) utility functions for computations involving polygons and polylines.\n\n## Usage\n\nYou just need to include `SphericalUtil.hpp` or `PolyUtil.hpp`\n\nHere is an example of using this library:\n\n```c++\n#include \u003ciostream\u003e\n#include \u003cvector\u003e\n\n#include \"SphericalUtil.hpp\"\n\nint main() {\n    LatLng up    = { 90.0,    0.0 };\n    LatLng down  = {-90.0,    0.0 };\n    LatLng front = {  0.0,    0.0 };\n    LatLng right = {  0.0,   90.0 };\n\n    auto angle = SphericalUtil::computeAngleBetween(up, right); // 90\n    std::cout \u003c\u003c \"The angle between up and right is \" \u003c\u003c rad2deg(angle) \u003c\u003c \" degrees\" \u003c\u003c std::endl;\n\n    auto distance = SphericalUtil::computeDistanceBetween(up, down); // 2.00151e+07\n    std::cout \u003c\u003c \"The distance between up and down is \" \u003c\u003c distance \u003c\u003c \" meters\" \u003c\u003c std::endl;\n\n    std::vector\u003cLatLng\u003e points = { front, up, right };\n\n    auto length = SphericalUtil::computeLength(points); // 2.00151e+07\n    std::cout \u003c\u003c \"The length between front, up and right is \" \u003c\u003c length \u003c\u003c \" meters\" \u003c\u003c std::endl;\n\n    auto area = SphericalUtil::computeArea(points); // 6.37582e+13\n    std::cout \u003c\u003c \"The area between front, up and right is \" \u003c\u003c area \u003c\u003c \" square meters\" \u003c\u003c std::endl;\n\n    return 0;\n}\n```\n\n## Available methods\n\n### PolyUtil class\n\n* [`containsLocation(LatLng point, LatLngList polygon,  bool geodesic)`](#containsLocation)\n* [`isLocationOnEdge(LatLng point, LatLngList polygon,  double tolerance, bool geodesic)`](#isLocationOnEdge)\n* [`isLocationOnPath(LatLng point, LatLngList polyline, double tolerance, bool geodesic)`](#isLocationOnPath)\n* [`distanceToLine(LatLng point, LatLng start, LatLng end)`](#distanceToLine)\n\n### SphericalUtil class\n\n* [`computeHeading(LatLng from, LatLng to)`](#computeHeading)\n* [`computeOffset(LatLng from, double distance, double heading)`](#computeOffset)\n* [`computeOffsetOrigin(LatLng to, double distance, double heading)`](#computeOffsetOrigin)\n* [`interpolate(LatLng from, LatLng to, double fraction)`](#interpolate)\n* [`computeDistanceBetween(LatLng from, LatLng to)`](#computeDistanceBetween)\n* [`computeLength(LatLngList path)`](#computeLength)\n* [`computeArea(LatLngList path)`](#computeArea)\n* [`computeSignedArea(LatLngList path)`](#computeSignedArea)\n\n## Classes description\n\n`LatLng` - a point in geographical coordinates: latitude and longitude.\n\n* Latitude  ranges between `-90` and `90` degrees, inclusive\n* Longitude ranges between `-180` and `180` degrees, inclusive\n\nUsage example:\n\n```c++\nLatLng northPole = {90, 0};\n\nLatLng otherPoint = northPole;\n```\n\n---\n\n`LatLngList` - a series of connected coordinates in an ordered sequence. Any iterable containers.\n\nUsage example:\n\n```c++\nstd::vector\u003cLatLng\u003e aroundNorthPole = { {89, 0}, {89, 120}, {89, -120} };\n\nstd::array\u003cLatLng, 1U\u003e northPole = { {90, 0} };\n```\n\n## Functions description\n\n### PolyUtil functions\n\n\u003ca name=\"containsLocation\"\u003e\u003c/a\u003e\n**`PolyUtil::containsLocation(const LatLng\u0026 point, const LatLngList\u0026 polygon, bool geodesic = false)`** - Computes whether the given point lies inside the specified polygon\n\n* `point` - a point in geographical coordinates: latitude and longitude\n* `polygon` - a series of connected coordinates in an ordered sequence\n* `geodesic` - the polyline is composed of great circle segments if geodesic is true, and of Rhumb segments otherwise\n\nReturn value: `bool` - whether the given point lies inside the specified polygon\n\n```c++\n// Around the north pole.\nstd::vector\u003cLatLng\u003e aroundNorthPole = { {89, 0}, {89, 120}, {89, -120} };\n\nstd::cout \u003c\u003c PolyUtil::containsLocation(LatLng(90, 0), aroundNorthPole);  // true\nstd::cout \u003c\u003c PolyUtil::containsLocation(LatLng(-90, 0), aroundNorthPole); // false\n```\n\n---\n\n\u003ca name=\"isLocationOnEdge\"\u003e\u003c/a\u003e\n**`PolyUtil::isLocationOnEdge(const LatLng\u0026 point, const LatLngList\u0026 polygon, double tolerance = PolyUtil::DEFAULT_TOLERANCE, bool geodesic = true)`** - Computes whether the given point lies on or near to a polyline, or the edge of a polygon, within a specified tolerance. Returns true when the difference between the latitude and longitude of the supplied point, and the closest point on the edge, is less than the tolerance. The tolerance defaults to `0.1` meters.\n\n* `point` - a point in geographical coordinates: latitude and longitude\n* `polygon` - a series of connected coordinates in an ordered sequence\n* `tolerance` - tolerance value in meters\n* `geodesic` - the polyline is composed of great circle segments if geodesic is true, and of Rhumb segments otherwise\n\nReturn value: `bool` - whether the given point lies on or near the edge of a polygon\n\n```c++\n// On equator.\nstd::vector\u003cLatLng\u003e equator = { {0, 90}, {0, 180} };\n\ndouble small = 5e-7; // Half the default tolerance.\ndouble big   = 2e-6; // Double the default tolerance.\n\nstd::cout \u003c\u003c PolyUtil::isLocationOnEdge(LatLng(0, 90 - small), equator); // true\nstd::cout \u003c\u003c PolyUtil::isLocationOnEdge(LatLng(0, 90 - big),   equator); // false\n```\n\n---\n\n\u003ca name=\"isLocationOnPath\"\u003e\u003c/a\u003e\n**`PolyUtil::isLocationOnPath(const LatLng\u0026 point, const LatLngList\u0026 polyline, double tolerance = PolyUtil::DEFAULT_TOLERANCE, bool geodesic = true)`** - Computes whether the given point lies on or near a polyline, within a specified tolerance in meters. The polyline is composed of great circle segments if geodesic is true, and of Rhumb segments otherwise. The polyline is not closed -- the closing segment between the first point and the last point is not included.\n\n* `point` - a point in geographical coordinates: latitude and longitude\n* `polygon` - a series of connected coordinates in an ordered sequence\n* `tolerance` - tolerance value in meters\n* `geodesic` - the polyline is composed of great circle segments if geodesic is true, and of Rhumb segments otherwise\n\nReturn value: `bool` - whether the point lies on or near a polyline\n\n```c++\n// On equator.\nstd::vector\u003cLatLng\u003e equator = { {0, 90}, {0, 180} };\n\ndouble small = 5e-7; // Half the default tolerance.\ndouble big   = 2e-6; // Double the default tolerance.\n\nstd::cout \u003c\u003c PolyUtil::isLocationOnPath(LatLng(0, 90 - small), equator); // true\nstd::cout \u003c\u003c PolyUtil::isLocationOnPath(LatLng(0, 90 - big),   equator); // false\n```\n\n---\n\n\u003ca name=\"distanceToLine\"\u003e\u003c/a\u003e\n**`PolyUtil::distanceToLine(const LatLng\u0026 p, const LatLng\u0026 start, const LatLng\u0026 end)`** - Computes the distance on the sphere between the point p and the line segment start to end.\n\n* `point` - the point to be measured\n* `start` - the beginning of the line segment\n* `end` - the end of the line segment\n\nReturn value: `double` - the distance in meters (assuming spherical earth)\n\n```c++\nLatLng startLine(28.05359, -82.41632);\nLatLng endLine(28.05310, -82.41634);\nLatLng point(28.05342, -82.41594);\n\nstd::cout \u003c\u003c PolyUtil::distanceToLine(point, startLine, endLine); // 37.947946\n```\n\n### SphericalUtil functions\n\n\u003ca name=\"computeHeading\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeHeading(const LatLng\u0026 from, const LatLng\u0026 to)`** - Returns the heading from one LatLng to another LatLng. Headings are expressed in degrees clockwise from North within the range [-180,180).\n\n* `from` - a point in geographical coordinates: latitude and longitude\n* `to` - a point in geographical coordinates: latitude and longitude\n\nReturn value: `double` - the heading in degrees clockwise from north\n\n```c++\nLatLng front(0,  0);\nLatLng right(0, 90);\n\nstd::cout \u003c\u003c SphericalUtil::computeHeading(right, front); // -90\nstd::cout \u003c\u003c SphericalUtil::computeHeading(front, right); // +90\n```\n\n---\n\n\u003ca name=\"computeOffset\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeOffset(const LatLng\u0026 from, double distance, double heading)`** - Returns the LatLng resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north).\n\n* `from` - the LatLng from which to start.\n* `distance` - the distance to travel.\n* `heading` - the heading in degrees clockwise from north.\n\nReturn value: `LatLng` - resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north)\n\n```c++\nLatLng front(0, 0);\n\nauto up    = SphericalUtil::computeOffset(front, M_PI * MathUtil::EARTH_RADIUS / 2,   0); // LatLng( 90,    0)\nauto down  = SphericalUtil::computeOffset(front, M_PI * MathUtil::EARTH_RADIUS / 2, 180); // LatLng(-90,    0)\nauto left  = SphericalUtil::computeOffset(front, M_PI * MathUtil::EARTH_RADIUS / 2, -90); // LatLng(  0,  -90)\nauto right = SphericalUtil::computeOffset(front, M_PI * MathUtil::EARTH_RADIUS / 2,  90); // LatLng(  0,   90)\nauto back  = SphericalUtil::computeOffset(front, M_PI * MathUtil::EARTH_RADIUS,      90); // LatLng(  0, -180)\n```\n\n---\n\n\u003ca name=\"computeOffsetOrigin\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeOffsetOrigin(const LatLng\u0026 to, double distance, double heading)`** - Returns the location of origin when provided with a LatLng destination, meters travelled and original heading. Headings are expressed in degrees clockwise from North.\n\n* `from` - the destination LatLng\n* `distance` - the distance travelled, in meters.\n* `heading` - the heading in degrees clockwise from north\n\nReturn value: `LatLng` - the location of origin when provided with a LatLng destination, meters travelled and original heading. Headings are expressed in degrees clockwise from North\n\n```c++\nLatLng front(0, 0);\n\nassert(front == SphericalUtil::computeOffsetOrigin(front, 0, 0));\n\nassert(front == SphericalUtil::computeOffsetOrigin(LatLng(  0,  45), M_PI * MathUtil::EARTH_RADIUS / 4,  90));\nassert(front == SphericalUtil::computeOffsetOrigin(LatLng(  0, -45), M_PI * MathUtil::EARTH_RADIUS / 4, -90));\nassert(front == SphericalUtil::computeOffsetOrigin(LatLng( 45,   0), M_PI * MathUtil::EARTH_RADIUS / 4,   0));\nassert(front == SphericalUtil::computeOffsetOrigin(LatLng(-45,   0), M_PI * MathUtil::EARTH_RADIUS / 4, 190));\n```\n\n---\n\n\u003ca name=\"interpolate\"\u003e\u003c/a\u003e\n**`SphericalUtil::interpolate(const LatLng\u0026 from, const LatLng\u0026 to, double fraction)`** - Returns the LatLng which lies the given fraction of the way between the origin LatLng and the destination LatLng.\n\n* `from` - the LatLng from which to start.\n* `to` - the LatLng toward which to travel.\n* `fraction` - a fraction of the distance to travel.\n\nReturn value: `LatLng` - point which lies the given fraction of the way between the origin LatLng and the destination LatLng\n\n```c++\nLatLng up(90, 0);\nLatLng front(0, 0);\n\nassert(LatLng(1,  0) == SphericalUtil::interpolate(front, up,  1 / 90.0));\nassert(LatLng(1,  0) == SphericalUtil::interpolate(up, front, 89 / 90.0));\nassert(LatLng(89, 0) == SphericalUtil::interpolate(front, up, 89 / 90.0));\nassert(LatLng(89, 0) == SphericalUtil::interpolate(up, front,  1 / 90.0));\n\n```\n\n---\n\n\u003ca name=\"computeDistanceBetween\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeDistanceBetween(const LatLng\u0026 from, const LatLng\u0026 to)`** - Returns the distance, in meters, between two LatLngs.\n\n* `from` - the first point\n* `to` - the second point\n\nReturn value: `double` - the distance, in meters, between two LatLngs\n\n```c++\nLatLng up(90, 0);\nLatLng down(-90, 0);\n\nstd:cout \u003c\u003c SphericalUtil::computeDistanceBetween(up, down); // MathUtil::EARTH_RADIUS\n```\n\n---\n\n\u003ca name=\"computeLength\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeLength(const LatLngList\u0026 path)`** - Returns the length of the given path, in meters, on Earth\n\n* `path` - a series of connected coordinates in an ordered sequence. Any iterable containers.\n\nReturn valuse: `double` - the length of the given path, in meters, on Earth\n\n```c++\n// List with three points\nstd::vector\u003cLatLng\u003e latLngs2 = { {0, 0}, {90, 0}, {0, 90} };\n\nstd::cout \u003c\u003c SphericalUtil::computeLength(latLngs2); // M_PI * MathUtil::EARTH_RADIUS\n```\n\n---\n\n\u003ca name=\"computeArea\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeArea(const LatLngList\u0026 path)`** - Returns the area of a closed path on Earth.\n\n* `path` - a closed path. Any iterable containers.\n\nReturn value: `double` - the area of a closed path on Earth\n\n```c++\nLatLng up    = { 90.0,  0.0 };\nLatLng down  = {-90.0,  0.0 };\nLatLng front = {  0.0,  0.0 };\nLatLng right = {  0.0, 90.0 };\n\nstd::vector\u003cLatLng\u003e path = { right, down, front, up, right };\n\nstd::cout \u003c\u003c SphericalUtil::computeArea(second); // M_PI * MathUtil::EARTH_RADIUS * MathUtil::EARTH_RADIUS\n```\n\n---\n\n\u003ca name=\"computeSignedArea\"\u003e\u003c/a\u003e\n**`SphericalUtil::computeSignedArea(const LatLngList\u0026 path)`** - Returns the signed area of a closed path on Earth. The sign of the area may be used to determine the orientation of the path. \"inside\" is the surface that does not contain the South Pole.\n\n* `path` - a closed path. Any iterable containers.\n\nReturn value: `double` - the loop's area in square meters\n\n```c++\nLatLng up    = { 90.0,    0.0 };\nLatLng down  = {-90.0,    0.0 };\nLatLng front = {  0.0,    0.0 };\nLatLng right = {  0.0,   90.0 };\n\nstd::vector\u003cLatLng\u003e path         = { right,   up, front, down, right };\nstd::vector\u003cLatLng\u003e pathReversed = { right, down, front,   up, right };\n\nassert(SphericalUtil::computeSignedArea(path) == -SphericalUtil::computeSignedArea(pathReversed));\n```\n\n---\n\n## Support\n\n[Please open an issue on GitHub](https://github.com/gistrec/cpp-geometry-library/issues)\n\n## License\n\nGeometry Library Google Maps API V3 is released under the MIT License.\nSee the bundled [LICENSE](https://github.com/alexpechkarev/geometry-library/blob/master/LICENSE) file for details.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgistrec%2Fcpp-geometry-library","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgistrec%2Fcpp-geometry-library","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgistrec%2Fcpp-geometry-library/lists"}