diff --git a/README.md b/README.md index fccf5b3..9d7f650 100644 --- a/README.md +++ b/README.md @@ -1,127 +1,34 @@ -# @aws-geospatial/polyline +# @aws/polyline -This library is used to simplify the process of using compressed geometry with [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) in JavaScript Applications. +This library simplifies the process of using compressed geometry with [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) in JavaScript applications +and with [maplibre-native](https://github.com/maplibre/maplibre-native) in Kotlin and Swift applications. Location-based service providers sometimes use variations of the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) -to reduce the response size for APIs that return potentially large arrays of coordinates, such as routing and isoline APIs. +to reduce the response size for APIs that can return large arrays of coordinates, such as routing and isoline APIs. The utility methods in this library compresses the data and decompresses into GeoJSON that can be directly rendered in MapLibre. -## Installation - -Install this library from NPM for usage with modules: - -```console -npm install @aws-geospatial/polyline -``` - -You can also import the Javascript file for usage directly in the browser. - -```html - -``` - ## Usage -Import the library and call the utility functions in the top-level namespace as needed. -You can find more details about these functions in the [Documentation](#documentation) section. - -### Usage with Modules - -```javascript -import { decodeToLineStringFeature } from "@aws-geospatial/polyline"; - -var decodedGeoJSON = decodeToLineStringFeature(response.EncodedPolyline); -map.addLayer({ - id: "route", - type: "line", - source: { - type: "geojson", - data: decodedGeoJSON, - }, - layout: { - "line-join": "round", - "line-cap": "round", - }, - paint: { - "line-color": "#3887be", - "line-width": 5, - "line-opacity": 0.75, - }, -}); -``` - -### Usage with a browser - -```html - - -``` - -```javascript -var decodedGeoJSON = polyline.decodeToLineStringFeature( - response.EncodedPolyline, -); -map.addLayer({ - id: "route", - type: "line", - source: { - type: "geojson", - data: decodedGeoJSON, - }, - layout: { - "line-join": "round", - "line-cap": "round", - }, - paint: { - "line-color": "#3887be", - "line-width": 5, - "line-opacity": 0.75, - }, -}); -``` - -## Documentation - -Detailed documentation can be found under `/docs/index.html` after generating it by running: - -```console -npm run typedoc -``` - -### encodeFromLngLatArray - -This encodes an array of coordinates in longitude, latitude order into compressed polyline data. -While this isn't needed for MapLibre rendering, you might need it to compress data for a request -to a Location Service Provider when requesting route-related data. - -### decodeToLineStringFeature - -This is the most common method to use. It decodes compressed polyline data into a GeoJSON -Feature containing a LineString that can directly be used as a MapLibre source for rendering. - -### decodeToPolygonFeature - -Similar to `decodeToLineStringFeature` it decodes an array of compressed polyline rings into a GeoJSON -Feature containing a Polygon that can directly be used as a MapLibre source for rendering. -This should be used when the compressed data is meant to represent polygon rings, as it will -also generate the correct winding order of the rings for use with GeoJSON. +Documentation for each supported language can be found here: +* [JavaScript](./javascript/README.md) +* [Kotlin](./kotlin/README.md) +* [Swift](./swift/README.md) -### decodeToLineString +## Security -This decodes a compressed polyline into a GeoJSON LineString. This can't directly be used -as a MapLibre source for rendering, but it is useful when trying to work directly with LineString -data. +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. -### decodeToPolygon +## Getting Help -This decodes an array of compressed polyline rings into a GeoJSON Polygon. This can't directly be used -as a MapLibre source for rendering, but it is useful when trying to work directly with Polygon -data. +The best way to interact with our team is through GitHub. +You can [open an issue](https://github.com/aws-geospatial/polyline/issues/new/choose) and choose from one of our templates for +[bug reports](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=bug%2C+needs-triage&template=---bug-report.md&title=) or +[feature requests](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=feature-request&template=---feature-request.md&title=). +If you have a support plan with [AWS Support](https://aws.amazon.com/premiumsupport/), you can also create a new support case. -### decodeToLngLatArray +## Contributing -This decodes compressed polyline data into an array of coordinates in longitude, latitude order. -This method is helpful when you need to directly work with the coordinate data. +We welcome community contributions and pull requests. See [CONTRIBUTING](CONTRIBUTING.md) for information on how to set up a development environment and submit code. ## License diff --git a/javascript/CODE_OF_CONDUCT.md b/javascript/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ec98f2b --- /dev/null +++ b/javascript/CODE_OF_CONDUCT.md @@ -0,0 +1,5 @@ +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/javascript/CONTRIBUTING.md b/javascript/CONTRIBUTING.md new file mode 100644 index 0000000..d0649a7 --- /dev/null +++ b/javascript/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional +documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +information to effectively respond to your bug report or contribution. + +## Reporting Bugs/Feature Requests + +We welcome you to use the GitHub issue tracker to report bugs or suggest features. + +When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already +reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: + +- A reproducible test case or series of steps +- The version of our code being used +- Any modifications you've made relevant to the bug +- Anything unusual about your environment or deployment + +## Contributing via Pull Requests + +Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: + +1. You are working against the latest source on the _main_ branch. +2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. +3. You open an issue to discuss any significant work - we would hate for your time to be wasted. + +To send us a pull request, please: + +1. Fork the repository. +2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. +3. Ensure local tests pass. +4. Commit to your fork using clear commit messages. +5. Send us a pull request, answering any default questions in the pull request interface. +6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + +## Finding contributions to work on + +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. + +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. + +## Security issue notifications + +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. + +## Licensing + +See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. diff --git a/javascript/LICENSE b/javascript/LICENSE new file mode 100644 index 0000000..09951d9 --- /dev/null +++ b/javascript/LICENSE @@ -0,0 +1,17 @@ +MIT No Attribution + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/javascript/README.md b/javascript/README.md new file mode 100644 index 0000000..350f185 --- /dev/null +++ b/javascript/README.md @@ -0,0 +1,189 @@ +# @aws/polyline + +This library simplifies the process of using compressed geometry with [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) in JavaScript applications. + +Location-based service providers sometimes use variations of the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) +to reduce the response size for APIs that can return large arrays of coordinates, such as routing and isoline APIs. +The utility methods in this library compresses the data and decompresses into GeoJSON that can be directly rendered in MapLibre. + +## Installation + +Install this library from NPM for usage with modules: + +```console +npm install @aws/polyline +``` + +You can also import the Javascript file for usage directly in the browser. + +```html + +``` + +## Usage + +Import the library and call the utility functions in the top-level namespace as needed. +You can find more details about these functions in the [Documentation](#documentation) section. + +### Usage with Modules + +```javascript +import { decodeToLineStringFeature } from "@aws/polyline"; + +var decodedGeoJSON = decodeToLineStringFeature(response.EncodedPolyline); +map.addLayer({ + id: "route", + type: "line", + source: { + type: "geojson", + data: decodedGeoJSON, + }, + layout: { + "line-join": "round", + "line-cap": "round", + }, + paint: { + "line-color": "#3887be", + "line-width": 5, + "line-opacity": 0.75, + }, +}); +``` + +### Usage with a browser + +```html + + +``` + +```javascript +var decodedGeoJSON = polyline.decodeToLineStringFeature( + response.EncodedPolyline, +); +map.addLayer({ + id: "route", + type: "line", + source: { + type: "geojson", + data: decodedGeoJSON, + }, + layout: { + "line-join": "round", + "line-cap": "round", + }, + paint: { + "line-color": "#3887be", + "line-width": 5, + "line-opacity": 0.75, + }, +}); +``` + +## Documentation + +Detailed documentation can be found under `/docs/index.html` after generating it by running: + +```console +npm run typedoc +``` + +### getCompressionAlgorithm + +Returns the currently-selected compression algorithm. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```js +const compressionType = polyline.getCompressionAlgorithm(); +``` + +### setCompressionAlgorithm + +Sets the compression algorithm to use for subsequent encode/decode calls. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```js +polyline.setCompressionAlgorithm(polyline.FlexiblePolyline); +``` + +### encodeFromLngLatArray + +This encodes an array of coordinates in longitude, latitude order into compressed polyline data. +The data can include an optional 3rd dimension when encoding with the `FlexiblePolyline` algorithm. +While this isn't needed for MapLibre rendering, you might need it to compress data for a request +to a Location Service Provider when requesting route-related data. + +```js +const polylineString = polyline.encodeFromLngLatArray([ + [5.0, 0.0], + [10.0, 0.0], +]); +``` + +### decodeToLineStringFeature + +This is the most common method to use. It decodes compressed polyline data into a GeoJSON +Feature containing a LineString that can directly be used as a MapLibre source for rendering. + +```js +const geoJsonLineStringFeature = + polyline.decodeToLineStringFeature(polylineString); +``` + +### decodeToPolygonFeature + +Similar to `decodeToLineStringFeature` it decodes an array of compressed polyline rings into a GeoJSON +Feature containing a Polygon that can directly be used as a MapLibre source for rendering. +This should be used when the compressed data is meant to represent polygon rings, as it will +also generate the correct winding order of the rings for use with GeoJSON. + +```js +const geoJsonPolygonFeature = polyline.decodeToPolygonFeature(polylineString); +``` + +### decodeToLineString + +This decodes a compressed polyline into a GeoJSON LineString. The LineString can be embedded into the `geometry` +section of a GeoJSON Feature which can then be rendered with MapLibre. + +```js +const geoJsonLineString = polyline.decodeToLineString(polylineString); +``` + +### decodeToPolygon + +This decodes an array of compressed polyline rings into a GeoJSON Polygon. The Polygon can be embedded into the +`geometry` section of a GeoJSON Feature which can then be rendered with MapLibre. + +```js +const geoJsonPolygon = polyline.decodeToPolygon(polylineString); +``` + +### decodeToLngLatArray + +This decodes compressed polyline data into an array of coordinates in longitude, latitude order. +This method is helpful when you need to directly work with the coordinate data. + +```js +const lngLatArray = polyline.decodeToLngLatArray(polylineString); +``` + +## Security + +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. + +## Getting Help + +The best way to interact with our team is through GitHub. +You can [open an issue](https://github.com/aws-geospatial/polyline/issues/new/choose) and choose from one of our templates for +[bug reports](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=bug%2C+needs-triage&template=---bug-report.md&title=) or +[feature requests](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=feature-request&template=---feature-request.md&title=). +If you have a support plan with [AWS Support](https://aws.amazon.com/premiumsupport/), you can also create a new support case. + +## Contributing + +We welcome community contributions and pull requests. See [CONTRIBUTING](CONTRIBUTING.md) for information on how to set up a development environment and submit code. + +## License + +This library is licensed under the MIT-0 License. See the [LICENSE](LICENSE) file. diff --git a/javascript/package-lock.json b/javascript/package-lock.json index 46dcdb5..4be274a 100644 --- a/javascript/package-lock.json +++ b/javascript/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@aws-geospatial/polyline", + "name": "@aws/polyline", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@aws-geospatial/polyline", + "name": "@aws/polyline", "version": "0.1.0", "license": "MIT", "dependencies": { @@ -26,6 +26,7 @@ "@typescript-eslint/parser": "^5.38.1", "eslint": "^8.56.0", "globals": "^15.6.0", + "husky": "^9.1.6", "jest": "^29.7.0", "npm-run-all": "^4.1.5", "prettier": "^3.2.5", @@ -6059,6 +6060,21 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "dev": true, + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", diff --git a/javascript/package.json b/javascript/package.json index b399249..6fd1a16 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -1,6 +1,13 @@ { - "name": "@aws-geospatial/polyline", + "name": "@aws/polyline", + "description": "A library for encoding and decoding polylines", "version": "0.1.0", + "keywords": [], + "author": { + "name": "Amazon Web Services", + "email": "", + "url": "https://aws.amazon.com/" + }, "license": "MIT", "homepage": "https://github.com/aws-geospatial/polyline", "repository": { @@ -16,7 +23,7 @@ "node": ">=18" }, "scripts": { - "clean": "rm -rf dist && rm -rf node_modules", + "clean": "rm -rf dist", "prettier": "prettier -w .", "prettier:check": "prettier -c .", "lint": "eslint .", @@ -27,20 +34,24 @@ "build-ts:types": "tsc --declaration --emitDeclarationOnly --outDir dist/types", "build-ts:cjs": "tsc --module commonjs --outDir dist/cjs", "build-ts:esm": "tsc --esModuleInterop --module esnext --outDir dist/esm", - "prepublishOnly": "npm run build && npm run test", + "prepare": "husky install", + "prepublishOnly": "npm-run-all clean lint prettier:check test build", "test": "jest --collectCoverage --collectCoverageFrom=src/**/*.{ts,js}", "typedoc": "typedoc" }, + "browser": "./dist/polyline.js", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", + "unpkg": "./dist/polyline.js", "types": "./dist/types/index.d.ts", "files": [ - "dist/", - "!**/__tests__/**" + "./LICENSE", + "./CODE_OF_CONDUCT.md", + "./CONTRIBUTING.md", + "./README.md", + "./package.json", + "./dist" ], - "npm-pretty-much": { - "runTest": "never" - }, "dependencies": { "@types/geojson": "^7946.0.10" }, @@ -59,6 +70,7 @@ "@typescript-eslint/parser": "^5.38.1", "eslint": "^8.56.0", "globals": "^15.6.0", + "husky": "^9.1.6", "jest": "^29.7.0", "npm-run-all": "^4.1.5", "prettier": "^3.2.5", diff --git a/kotlin/CODE_OF_CONDUCT.md b/kotlin/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ec98f2b --- /dev/null +++ b/kotlin/CODE_OF_CONDUCT.md @@ -0,0 +1,5 @@ +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/kotlin/CONTRIBUTING.md b/kotlin/CONTRIBUTING.md new file mode 100644 index 0000000..d0649a7 --- /dev/null +++ b/kotlin/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional +documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +information to effectively respond to your bug report or contribution. + +## Reporting Bugs/Feature Requests + +We welcome you to use the GitHub issue tracker to report bugs or suggest features. + +When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already +reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: + +- A reproducible test case or series of steps +- The version of our code being used +- Any modifications you've made relevant to the bug +- Anything unusual about your environment or deployment + +## Contributing via Pull Requests + +Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: + +1. You are working against the latest source on the _main_ branch. +2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. +3. You open an issue to discuss any significant work - we would hate for your time to be wasted. + +To send us a pull request, please: + +1. Fork the repository. +2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. +3. Ensure local tests pass. +4. Commit to your fork using clear commit messages. +5. Send us a pull request, answering any default questions in the pull request interface. +6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + +## Finding contributions to work on + +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. + +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. + +## Security issue notifications + +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. + +## Licensing + +See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. diff --git a/kotlin/LICENSE b/kotlin/LICENSE new file mode 100644 index 0000000..09951d9 --- /dev/null +++ b/kotlin/LICENSE @@ -0,0 +1,17 @@ +MIT No Attribution + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/kotlin/README.md b/kotlin/README.md new file mode 100644 index 0000000..f7d4181 --- /dev/null +++ b/kotlin/README.md @@ -0,0 +1,165 @@ +# Polyline for Kotlin + +This library simplifies the process of using compressed geometry with [maplibre-native](https://github.com/maplibre/maplibre-native) in Kotlin applications. + +Location-based service providers sometimes use variations of the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) +to reduce the response size for APIs that can return large arrays of coordinates, such as routing and isoline APIs. +The utility methods in this library compresses the data and decompresses into GeoJSON that can be directly rendered in MapLibre. + +## Installation + +Add the following line to the dependencies section of your build.gradle or build.gradle.kts file in Android Studio: + +```console +implementation("software.amazon.location:polyline:0.1.0") +``` + +## Usage + +Import the Polyline class in your code: +```kotlin +import software.amazon.location.polyline.Polyline +``` + +To decode a routePolyline and render it in MapLibre, you can use the following: + +```kotlin +val decodedGeoJSON = when (val result = Polyline.decodeToLineStringFeature(routePolyline)) { + is Polyline.DecodeToGeoJsonResult.Success -> result.geojson + is Polyline.DecodeToGeoJsonResult.Error -> "" +} + +style.addSource( + GeoJsonSource( + "polylineSource", + decodedGeoJSON, + GeoJsonOptions().withLineMetrics(true) + ) +) + +style.addLayer( + LineLayer("polyline", "polylineSource") + .withProperties( + PropertyFactory.lineColor(Color.RED), + PropertyFactory.lineWidth(2.0f), + PropertyFactory.lineCap(Property.LINE_CAP_ROUND), + PropertyFactory.lineJoin(Property.LINE_JOIN_ROUND) + ) +) +``` + +## Documentation + +### getCompressionAlgorithm + +Returns the currently-selected compression algorithm. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```kotlin +val compressionType = Polyline.getCompressionAlgorithm() +``` + +### setCompressionAlgorithm + +Sets the compression algorithm to use for subsequent encode/decode calls. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```kotlin +Polyline.setCompressionAlgorithm(Polyline.CompressionAlgorithm.FlexiblePolyline) +``` + +### encodeFromLngLatArray + +This encodes an array of coordinates in longitude, latitude order into compressed polyline data. +The data can include an optional 3rd dimension when encoding with the `FlexiblePolyline` algorithm. +While this isn't needed for MapLibre rendering, you might need it to compress data for a request +to a Location Service Provider when requesting route-related data. + +```kotlin +val polylineString = when (val result = Polyline.encodeFromLngLatArray(arrayOf(doubleArrayOf(5.0, 0.0), doubleArrayOf(10.0, 0.0)))) { + is Polyline.EncodeResult.Success -> result.encodedData + is Polyline.EncodeResult.Error -> "" +} +``` + +### decodeToLineStringFeature + +This is the most common method to use. It decodes compressed polyline data into a GeoJSON +Feature containing a LineString that can directly be used as a MapLibre source for rendering. + +```kotlin +val geoJsonLineStringFeature = when (val result = Polyline.decodeToLineStringFeature(polylineString)) { + is Polyline.DecodeToGeoJsonResult.Success -> result.geojson + is Polyline.DecodeToGeoJsonResult.Error -> "" +} +``` + +### decodeToPolygonFeature + +Similar to `decodeToLineStringFeature` it decodes an array of compressed polyline rings into a GeoJSON +Feature containing a Polygon that can directly be used as a MapLibre source for rendering. +This should be used when the compressed data is meant to represent polygon rings, as it will +also generate the correct winding order of the rings for use with GeoJSON. + +```kotlin +val geoJsonPolygonFeature = when (val result = Polyline.decodeToPolygonFeature(polylineString)) { + is Polyline.DecodeToGeoJsonResult.Success -> result.geojson + is Polyline.DecodeToGeoJsonResult.Error -> "" +} +``` + +### decodeToLineString + +This decodes a compressed polyline into a GeoJSON LineString. The LineString can be embedded into the `geometry` +section of a GeoJSON Feature which can then be rendered with MapLibre. + +```kotlin +val geoJsonLineString = when (val result = Polyline.decodeToLineString(polylineString)) { + is Polyline.DecodeToGeoJsonResult.Success -> result.geojson + is Polyline.DecodeToGeoJsonResult.Error -> "" +} +``` + +### decodeToPolygon + +This decodes an array of compressed polyline rings into a GeoJSON Polygon. The Polygon can be embedded into the +`geometry` section of a GeoJSON Feature which can then be rendered with MapLibre. + +```kotlin +val geoJsonPolygon = when (val result = Polyline.decodeToPolygon(polylineString)) { + is Polyline.DecodeToGeoJsonResult.Success -> result.geojson + is Polyline.DecodeToGeoJsonResult.Error -> "" +} +``` + +### decodeToLngLatArray + +This decodes compressed polyline data into an array of coordinates in longitude, latitude order. +This method is helpful when you need to directly work with the coordinate data. + +```kotlin +val lngLatArray = when (val result = Polyline.decodeToLngLatArray(polylineString)) { + is Polyline.DecodeToArrayResult.Success -> result.lngLatArray + is Polyline.DecodeToArrayResult.Error -> null +} +``` + +## Security + +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. + +## Getting Help + +The best way to interact with our team is through GitHub. +You can [open an issue](https://github.com/aws-geospatial/polyline/issues/new/choose) and choose from one of our templates for +[bug reports](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=bug%2C+needs-triage&template=---bug-report.md&title=) or +[feature requests](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=feature-request&template=---feature-request.md&title=). +If you have a support plan with [AWS Support](https://aws.amazon.com/premiumsupport/), you can also create a new support case. + +## Contributing + +We welcome community contributions and pull requests. See [CONTRIBUTING](CONTRIBUTING.md) for information on how to set up a development environment and submit code. + +## License + +This library is licensed under the MIT-0 License. See the [LICENSE](LICENSE) file. diff --git a/kotlin/polyline/build.gradle.kts b/kotlin/polyline/build.gradle.kts index f33bfdc..60d0045 100644 --- a/kotlin/polyline/build.gradle.kts +++ b/kotlin/polyline/build.gradle.kts @@ -1,6 +1,52 @@ +import com.vanniktech.maven.publish.SonatypeHost + plugins { id("java-library") alias(libs.plugins.jetbrainsKotlinJvm) + id("com.vanniktech.maven.publish") version "0.27.0" +} + +publishing { + repositories { + maven { + name = "Polyline" + url = uri("https://aws.oss.sonatype.org/service/local/staging/deploy/maven2/") + credentials(PasswordCredentials::class) + } + } +} + +mavenPublishing { + publishToMavenCentral(SonatypeHost.DEFAULT, automaticRelease = true) + signAllPublications() + + coordinates("software.amazon.location", "polyline", "0.1.0") + + pom { + name.set("Polyline library for Kotlin") + description.set("A library for encoding and decoding polylines.") + inceptionYear.set("2024") + url.set("https://github.com/aws-geospatial/polyline") + licenses { + license { + name.set("MIT No Attribution License") + url.set("https://opensource.org/license/mit-0") + distribution.set("https://opensource.org/license/mit-0") + } + } + developers { + developer { + id.set("aws-geospatial") + name.set("AWS Geospatial") + url.set("https://github.com/aws-geospatial") + } + } + scm { + url.set("https://github.com/aws-geospatial/polyline") + connection.set("scm:git:git://github.com/aws-geospatial/polyline") + developerConnection.set("scm:git:ssh://git@github.com/aws-geospatial/polyline") + } + } } java { diff --git a/swift/CODE_OF_CONDUCT.md b/swift/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ec98f2b --- /dev/null +++ b/swift/CODE_OF_CONDUCT.md @@ -0,0 +1,5 @@ +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/swift/CONTRIBUTING.md b/swift/CONTRIBUTING.md new file mode 100644 index 0000000..d0649a7 --- /dev/null +++ b/swift/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional +documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +information to effectively respond to your bug report or contribution. + +## Reporting Bugs/Feature Requests + +We welcome you to use the GitHub issue tracker to report bugs or suggest features. + +When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already +reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: + +- A reproducible test case or series of steps +- The version of our code being used +- Any modifications you've made relevant to the bug +- Anything unusual about your environment or deployment + +## Contributing via Pull Requests + +Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: + +1. You are working against the latest source on the _main_ branch. +2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. +3. You open an issue to discuss any significant work - we would hate for your time to be wasted. + +To send us a pull request, please: + +1. Fork the repository. +2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. +3. Ensure local tests pass. +4. Commit to your fork using clear commit messages. +5. Send us a pull request, answering any default questions in the pull request interface. +6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + +## Finding contributions to work on + +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. + +## Code of Conduct + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. + +## Security issue notifications + +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. + +## Licensing + +See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. diff --git a/swift/LICENSE b/swift/LICENSE new file mode 100644 index 0000000..09951d9 --- /dev/null +++ b/swift/LICENSE @@ -0,0 +1,17 @@ +MIT No Attribution + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/swift/Polyline/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/swift/Polyline/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/swift/Polyline/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/swift/Polyline/Sources/Polyline/DataCompressor.swift b/swift/Polyline/Sources/Polyline/DataCompressor.swift index 49a24a3..a42a667 100644 --- a/swift/Polyline/Sources/Polyline/DataCompressor.swift +++ b/swift/Polyline/Sources/Polyline/DataCompressor.swift @@ -102,7 +102,7 @@ class DataCompressor { """ { "type": "LineString", - "coordinates": \(decodedLine), + "coordinates": \(decodedLine) } """, compressionParameters @@ -169,7 +169,7 @@ class DataCompressor { """ { "type": "Polygon", - "coordinates": \(decodedPolygon), + "coordinates": \(decodedPolygon) } """, compressionParameters @@ -185,7 +185,7 @@ class DataCompressor { { "precision": \(parameters.precisionLngLat), "thirdDimensionPrecision": \(parameters.precisionThirdDimension), - "thirdDimensionType": "level", + "thirdDimensionType": "level" } """; case ThirdDimension.Elevation: @@ -193,7 +193,7 @@ class DataCompressor { { "precision": \(parameters.precisionLngLat), "thirdDimensionPrecision": \(parameters.precisionThirdDimension), - "thirdDimensionType": "elevation", + "thirdDimensionType": "elevation" } """; case ThirdDimension.Altitude: @@ -201,7 +201,7 @@ class DataCompressor { { "precision": \(parameters.precisionLngLat), "thirdDimensionPrecision": \(parameters.precisionThirdDimension), - "thirdDimensionType": "altitude", + "thirdDimensionType": "altitude" } """; default: @@ -242,7 +242,7 @@ class DataCompressor { { "type": "Feature", "geometry": \(lineString), - "properties": \(self.compressionParametersToGeoJsonProperties(parameters: compressionParameters)), + "properties": \(self.compressionParametersToGeoJsonProperties(parameters: compressionParameters)) } """; } @@ -253,7 +253,7 @@ class DataCompressor { { "type": "Feature", "geometry": \(polygon), - "properties": \(self.compressionParametersToGeoJsonProperties(parameters: compressionParameters)), + "properties": \(self.compressionParametersToGeoJsonProperties(parameters: compressionParameters)) } """; } diff --git a/swift/Polyline/Sources/Polyline/Polyline.swift b/swift/Polyline/Sources/Polyline/Polyline.swift index 6c2966e..95fd3a3 100644 --- a/swift/Polyline/Sources/Polyline/Polyline.swift +++ b/swift/Polyline/Sources/Polyline/Polyline.swift @@ -10,7 +10,7 @@ private var compressor: DataCompressor = FlexiblePolyline(); /** Get the currently-selected compression algorithm. * @returns The current compression algorithm. */ -func getCompressionAlgorithm() -> CompressionAlgorithm { +public func getCompressionAlgorithm() -> CompressionAlgorithm { if (compressor is Polyline5) { return CompressionAlgorithm.Polyline5; } @@ -25,7 +25,7 @@ func getCompressionAlgorithm() -> CompressionAlgorithm { * @param compressionType The compression algorithm to use. * @throws Error() if an invalid compression algorithm is specified. */ -func setCompressionAlgorithm(_ compressionType: CompressionAlgorithm = .FlexiblePolyline) { +public func setCompressionAlgorithm(_ compressionType: CompressionAlgorithm = .FlexiblePolyline) { switch (compressionType) { case CompressionAlgorithm.Polyline5: if (!(compressor is Polyline5)) { @@ -61,7 +61,7 @@ func setCompressionAlgorithm(_ compressionType: CompressionAlgorithm = .Flexible * latitude values outside of [-90, 90], longitude values outside of [-180, 180], * data that isn't 2-dimensional or 3-dimensional, or data that is 3-dimensional with a compressor that doesn't support 3D data. */ -func encodeFromLngLatArray( +public func encodeFromLngLatArray( lngLatArray: Array>, parameters: CompressionParameters = CompressionParameters() ) throws -> String { @@ -88,7 +88,7 @@ func encodeFromLngLatArray( * ] * ``` */ -func decodeToLngLatArray( +public func decodeToLngLatArray( _ encodedData: String ) throws -> Array> { return try compressor.decodeToLngLatArray(compressedData: encodedData); @@ -117,7 +117,7 @@ func decodeToLngLatArray( * } * ``` */ -func decodeToLineString(_ encodedData: String) throws -> String { +public func decodeToLineString(_ encodedData: String) throws -> String { return try compressor.decodeToLineString(compressedData: encodedData); } @@ -149,7 +149,7 @@ func decodeToLineString(_ encodedData: String) throws -> String { * } * ``` */ -func decodeToPolygon(_ encodedData: Array) throws -> String { +public func decodeToPolygon(_ encodedData: Array) throws -> String { return try compressor.decodeToPolygon(compressedData: encodedData); } @@ -198,7 +198,7 @@ func decodeToPolygon(_ encodedData: Array) throws -> String { * }); * ``` */ -func decodeToLineStringFeature(_ encodedData: String) throws -> String { +public func decodeToLineStringFeature(_ encodedData: String) throws -> String { return try compressor.decodeToLineStringFeature(compressedData: encodedData); } @@ -248,6 +248,6 @@ func decodeToLineStringFeature(_ encodedData: String) throws -> String { * }); * ``` */ -func decodeToPolygonFeature(_ encodedData: Array) throws -> String { +public func decodeToPolygonFeature(_ encodedData: Array) throws -> String { return try compressor.decodeToPolygonFeature(compressedData: encodedData); } diff --git a/swift/Polyline/Sources/Polyline/PolylineTypes.swift b/swift/Polyline/Sources/Polyline/PolylineTypes.swift index 0eb79b2..1b9896d 100644 --- a/swift/Polyline/Sources/Polyline/PolylineTypes.swift +++ b/swift/Polyline/Sources/Polyline/PolylineTypes.swift @@ -4,13 +4,13 @@ import Foundation /** Defines the default encoding precision for coordinates */ -let DefaultPrecision = 6; +public let DefaultPrecision = 6; /** The version of flexible-polyline that's supported by this implementation */ let FlexiblePolylineFormatVersion = 1; /** Defines the set of compression algorithms that are supported by this library. */ -enum CompressionAlgorithm { +public enum CompressionAlgorithm { /** Encoder/decoder for the [Flexible Polyline](https://github.com/heremaps/flexible-polyline) format. */ case FlexiblePolyline /** Encoder/decoder for the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) @@ -24,7 +24,7 @@ enum CompressionAlgorithm { } /** Defines how to interpret a third dimension value if it exists. */ -enum ThirdDimension:Int { +public enum ThirdDimension:Int { /** No third dimension specified */ case None = 0 /** Third dimension is level */ @@ -40,18 +40,18 @@ enum ThirdDimension:Int { * algorithms ignore them, as they don't support 3D data and we've defined them to use * a fixed precision value. */ -struct CompressionParameters { +public struct CompressionParameters { /** The number of decimal places of precision to use for compressing longitude and latitude. */ - let precisionLngLat: Int; + public let precisionLngLat: Int; /** The number of decimal places of precision to use for compressing the third dimension of data. */ - let precisionThirdDimension: Int; + public let precisionThirdDimension: Int; /** The type of third dimension data being encoded - none, level, altitude, or elevation. */ - let thirdDimension: ThirdDimension; + public let thirdDimension: ThirdDimension; - init(precisionLngLat: Int = DefaultPrecision, precisionThirdDimension: Int = 0, thirdDimension: ThirdDimension = ThirdDimension.None) { + public init(precisionLngLat: Int = DefaultPrecision, precisionThirdDimension: Int = 0, thirdDimension: ThirdDimension = ThirdDimension.None) { self.precisionLngLat = precisionLngLat; self.precisionThirdDimension = precisionThirdDimension; self.thirdDimension = thirdDimension; @@ -59,7 +59,7 @@ struct CompressionParameters { }; -enum DecodeError: Error { +public enum DecodeError: Error { // Empty input string is considered an error. case emptyInput // Invalid input, the encoded character doesn't exist in the decoding table. @@ -75,7 +75,7 @@ enum DecodeError: Error { }; -enum EncodeError: Error { +public enum EncodeError: Error { // Invalid precision value, the valid range is 0 - 11. case invalidPrecisionValue // All the coordinates need to have the same number of dimensions. @@ -85,7 +85,7 @@ enum EncodeError: Error { }; -enum GeoJsonError: Error { +public enum GeoJsonError: Error { // LineString coordinate arrays need at least 2 entries (start, end) case invalidLineStringLength // Polygon coordinate arrays need at least 4 entries (v0, v1, v2, v0) diff --git a/swift/PolylineDemo/PolylineDemo.xcodeproj/project.pbxproj b/swift/PolylineDemo/PolylineDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2293c46 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo.xcodeproj/project.pbxproj @@ -0,0 +1,405 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 685E1E472CAEF07000F2C626 /* PolylineDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 685E1E462CAEF07000F2C626 /* PolylineDemoApp.swift */; }; + 685E1E492CAEF07000F2C626 /* SimpleMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 685E1E482CAEF07000F2C626 /* SimpleMap.swift */; }; + 685E1E4B2CAEF07100F2C626 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 685E1E4A2CAEF07100F2C626 /* Assets.xcassets */; }; + 685E1E4E2CAEF07100F2C626 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 685E1E4D2CAEF07100F2C626 /* Preview Assets.xcassets */; }; + 685E1E562CAEF43000F2C626 /* MapLibre in Frameworks */ = {isa = PBXBuildFile; productRef = 685E1E552CAEF43000F2C626 /* MapLibre */; }; + 68AE0BB32CB894B600AF75CF /* Polyline in Frameworks */ = {isa = PBXBuildFile; productRef = 68AE0BB22CB894B600AF75CF /* Polyline */; }; + 68AE0BB62CB968FE00AF75CF /* Polyline in Frameworks */ = {isa = PBXBuildFile; productRef = 68AE0BB52CB968FE00AF75CF /* Polyline */; }; + 68AE0BB92CB9695100AF75CF /* Polyline in Frameworks */ = {isa = PBXBuildFile; productRef = 68AE0BB82CB9695100AF75CF /* Polyline */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 685E1E432CAEF07000F2C626 /* PolylineDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PolylineDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 685E1E462CAEF07000F2C626 /* PolylineDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolylineDemoApp.swift; sourceTree = ""; }; + 685E1E482CAEF07000F2C626 /* SimpleMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMap.swift; sourceTree = ""; }; + 685E1E4A2CAEF07100F2C626 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 685E1E4D2CAEF07100F2C626 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 685E1E402CAEF07000F2C626 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68AE0BB92CB9695100AF75CF /* Polyline in Frameworks */, + 68AE0BB32CB894B600AF75CF /* Polyline in Frameworks */, + 685E1E562CAEF43000F2C626 /* MapLibre in Frameworks */, + 68AE0BB62CB968FE00AF75CF /* Polyline in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 685E1E3A2CAEF07000F2C626 = { + isa = PBXGroup; + children = ( + 685E1E452CAEF07000F2C626 /* PolylineDemo */, + 685E1E442CAEF07000F2C626 /* Products */, + ); + sourceTree = ""; + }; + 685E1E442CAEF07000F2C626 /* Products */ = { + isa = PBXGroup; + children = ( + 685E1E432CAEF07000F2C626 /* PolylineDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 685E1E452CAEF07000F2C626 /* PolylineDemo */ = { + isa = PBXGroup; + children = ( + 685E1E462CAEF07000F2C626 /* PolylineDemoApp.swift */, + 685E1E482CAEF07000F2C626 /* SimpleMap.swift */, + 685E1E4A2CAEF07100F2C626 /* Assets.xcassets */, + 685E1E4C2CAEF07100F2C626 /* Preview Content */, + ); + path = PolylineDemo; + sourceTree = ""; + }; + 685E1E4C2CAEF07100F2C626 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 685E1E4D2CAEF07100F2C626 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 685E1E422CAEF07000F2C626 /* PolylineDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 685E1E512CAEF07100F2C626 /* Build configuration list for PBXNativeTarget "PolylineDemo" */; + buildPhases = ( + 685E1E3F2CAEF07000F2C626 /* Sources */, + 685E1E402CAEF07000F2C626 /* Frameworks */, + 685E1E412CAEF07000F2C626 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PolylineDemo; + packageProductDependencies = ( + 685E1E552CAEF43000F2C626 /* MapLibre */, + 68AE0BB22CB894B600AF75CF /* Polyline */, + 68AE0BB52CB968FE00AF75CF /* Polyline */, + 68AE0BB82CB9695100AF75CF /* Polyline */, + ); + productName = PolylineDemo; + productReference = 685E1E432CAEF07000F2C626 /* PolylineDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 685E1E3B2CAEF07000F2C626 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1520; + LastUpgradeCheck = 1520; + TargetAttributes = { + 685E1E422CAEF07000F2C626 = { + CreatedOnToolsVersion = 15.2; + }; + }; + }; + buildConfigurationList = 685E1E3E2CAEF07000F2C626 /* Build configuration list for PBXProject "PolylineDemo" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 685E1E3A2CAEF07000F2C626; + packageReferences = ( + 685E1E542CAEF43000F2C626 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */, + 68AE0BB72CB9695100AF75CF /* XCLocalSwiftPackageReference "../../../../../polyline" */, + ); + productRefGroup = 685E1E442CAEF07000F2C626 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 685E1E422CAEF07000F2C626 /* PolylineDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 685E1E412CAEF07000F2C626 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 685E1E4E2CAEF07100F2C626 /* Preview Assets.xcassets in Resources */, + 685E1E4B2CAEF07100F2C626 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 685E1E3F2CAEF07000F2C626 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 685E1E492CAEF07000F2C626 /* SimpleMap.swift in Sources */, + 685E1E472CAEF07000F2C626 /* PolylineDemoApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 685E1E4F2CAEF07100F2C626 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 685E1E502CAEF07100F2C626 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 685E1E522CAEF07100F2C626 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"PolylineDemo/Preview Content\""; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.amazon.PolylineDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 685E1E532CAEF07100F2C626 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"PolylineDemo/Preview Content\""; + DEVELOPMENT_TEAM = ""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.amazon.PolylineDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 685E1E3E2CAEF07000F2C626 /* Build configuration list for PBXProject "PolylineDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 685E1E4F2CAEF07100F2C626 /* Debug */, + 685E1E502CAEF07100F2C626 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 685E1E512CAEF07100F2C626 /* Build configuration list for PBXNativeTarget "PolylineDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 685E1E522CAEF07100F2C626 /* Debug */, + 685E1E532CAEF07100F2C626 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 68AE0BB72CB9695100AF75CF /* XCLocalSwiftPackageReference "../../../../../polyline" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = ../../../../../polyline; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 685E1E542CAEF43000F2C626 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/maplibre/maplibre-gl-native-distribution"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 6.7.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 685E1E552CAEF43000F2C626 /* MapLibre */ = { + isa = XCSwiftPackageProductDependency; + package = 685E1E542CAEF43000F2C626 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */; + productName = MapLibre; + }; + 68AE0BB22CB894B600AF75CF /* Polyline */ = { + isa = XCSwiftPackageProductDependency; + productName = Polyline; + }; + 68AE0BB52CB968FE00AF75CF /* Polyline */ = { + isa = XCSwiftPackageProductDependency; + productName = Polyline; + }; + 68AE0BB82CB9695100AF75CF /* Polyline */ = { + isa = XCSwiftPackageProductDependency; + productName = Polyline; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 685E1E3B2CAEF07000F2C626 /* Project object */; +} diff --git a/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swift/PolylineDemo/PolylineDemo/Assets.xcassets/Contents.json b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swift/PolylineDemo/PolylineDemo/PolylineDemoApp.swift b/swift/PolylineDemo/PolylineDemo/PolylineDemoApp.swift new file mode 100644 index 0000000..63b1c47 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/PolylineDemoApp.swift @@ -0,0 +1,17 @@ +// +// PolylineDemoApp.swift +// PolylineDemo +// +// Created by Balfour, Mike on 10/3/24. +// + +import SwiftUI + +@main +struct PolylineDemoApp: App { + var body: some Scene { + WindowGroup { + SimpleMap() + } + } +} diff --git a/swift/PolylineDemo/PolylineDemo/Preview Content/Preview Assets.xcassets/Contents.json b/swift/PolylineDemo/PolylineDemo/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swift/PolylineDemo/PolylineDemo/SimpleMap.swift b/swift/PolylineDemo/PolylineDemo/SimpleMap.swift new file mode 100644 index 0000000..1951e70 --- /dev/null +++ b/swift/PolylineDemo/PolylineDemo/SimpleMap.swift @@ -0,0 +1,109 @@ +// +// ContentView.swift +// PolylineDemo +// +// Created by Balfour, Mike on 10/3/24. +// + +import SwiftUI +import MapLibre +import Polyline + +class Coordinator: NSObject, MLNMapViewDelegate { + var parent: SimpleMap + + init(_ parent: SimpleMap) { + self.parent = parent + } + + func mapView(_ mapView: MLNMapView, didFinishLoading style: MLNStyle) { + addPolyline(to: mapView) + } + + func addPolyline(to mapView: MLNMapView) { + let lngLatArray: [[Double]] = [ + [-28.193, -61.38823], + [-26.78675, -45.01442], + [-9.20863, -43.2583], + [-9.20863, -52.20348], + [-26.78675, -53.26775], + [-28.193, -61.38823], + [-20.10706, -61.21942], + [-19.05238, -57.07888], + [-8.85706, -57.07888], + [-9.20863, -61.21942], + [-20.10706, -61.21942], + [-0.068, -60.70753], + [2.7445, -43.75829], + [-0.068, -60.70753], + [11.182, -60.53506], + [6.96325, -55.11851], + [11.182, -60.53506], + [16.807, -54.51079], + [3.47762, -65.61471], + [11.182, -60.53506], + [22.432, -60.18734], + [25.59606, -42.99168], + [22.432, -60.18734], + [31.22106, -59.83591], + [32.62731, -53.05697], + [31.22106, -59.83591], + [38.25231, -59.65879], + [40.36169, -53.05697], + [40.01012, -54.71438], + [44.22887, -53.26775], + [47.39294, -55.5186], + [46.68981, -59.65879], + [53.72106, -59.30172], + [51.26012, -56.11118], + [56.182, -53.89389], + [60.40075, -56.69477], + [51.26012, -56.11118], + [53.72106, -59.30172], + [58.64294, -59.48073] + ] + + do { + // Encode and decode the route polyline to demonstrate how the APIs are used. + let routePolyline = try Polyline.encodeFromLngLatArray(lngLatArray: lngLatArray) + let decodedGeoJSON = try Polyline.decodeToLineStringFeature(routePolyline) + + let shapeFromGeoJSON = try MLNShape(data: decodedGeoJSON.data(using: .utf8)!, encoding: String.Encoding.utf8.rawValue) + + let source = MLNShapeSource(identifier: "polylineSource", shape: shapeFromGeoJSON, options: nil) + mapView.style?.addSource(source) + + let lineLayer = MLNLineStyleLayer(identifier: "polyline", source: source) + lineLayer.lineColor = NSExpression(forConstantValue: UIColor.red) + lineLayer.lineWidth = NSExpression(forConstantValue: 2) + lineLayer.lineJoin = NSExpression(forConstantValue: "round") + lineLayer.lineCap = NSExpression(forConstantValue: "round") + + mapView.style?.addLayer(lineLayer) + } + catch { + print("Error: \(error)") + } + + } +} + +struct SimpleMap: UIViewRepresentable { + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } + + func updateUIView(_ uiView: MLNMapView, context: Context) {} + + func makeUIView(context: Context) -> MLNMapView { + let mapView = MLNMapView() + mapView.delegate = context.coordinator + mapView.styleURL = URL(string: "https://demotiles.maplibre.org/style.json") + return mapView + } +} + +#Preview { + SimpleMap() +} diff --git a/swift/README.md b/swift/README.md new file mode 100644 index 0000000..def0614 --- /dev/null +++ b/swift/README.md @@ -0,0 +1,154 @@ +# Polyline for Kotlin + +This library simplifies the process of using compressed geometry with [maplibre-native](https://github.com/maplibre/maplibre-native) in Swift applications. + +Location-based service providers sometimes use variations of the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) +to reduce the response size for APIs that can return large arrays of coordinates, such as routing and isoline APIs. +The utility methods in this library compresses the data and decompresses into GeoJSON that can be directly rendered in MapLibre. + +## Installation + +1. Go to File -> Add Package Dependencies in your XCode project. +2. Type the package URL (https://github.com/aws-geospatial/polyline/) into the search bar and press the enter key. +3. Select the "polyline" package and click on "Add Package". +4. Select the "polyline" package product and click on "Add Package". + +## Usage + +Import the Polyline package in your code: +```swift +import Polyline +``` + +To decode a routePolyline and render it in MapLibre, you can use the following: + +```swift +do { + let decodedGeoJSON = try Polyline.decodeToLineStringFeature(routePolyline) + + let shapeFromGeoJSON = try MLNShape(data: decodedGeoJSON.data(using: .utf8)!, encoding: String.Encoding.utf8.rawValue) + + let source = MLNShapeSource(identifier: "polylineSource", shape: shapeFromGeoJSON, options: nil) + mapView.style?.addSource(source) + + let lineLayer = MLNLineStyleLayer(identifier: "polyline", source: source) + lineLayer.lineColor = NSExpression(forConstantValue: UIColor.red) + lineLayer.lineWidth = NSExpression(forConstantValue: 2) + lineLayer.lineJoin = NSExpression(forConstantValue: "round") + lineLayer.lineCap = NSExpression(forConstantValue: "round") + + mapView.style?.addLayer(lineLayer) +} catch { + print("Error: \(error)") +} +``` + +## Documentation + +### getCompressionAlgorithm + +Returns the currently-selected compression algorithm. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```swift +val compressionType = Polyline.getCompressionAlgorithm() +``` + +### setCompressionAlgorithm + +Sets the compression algorithm to use for subsequent encode/decode calls. This can be either +`FlexiblePolyline`, `Polyline5`, or `Polyline6`. + +```swift +Polyline.setCompressionAlgorithm(Polyline.CompressionAlgorithm.FlexiblePolyline) +``` + +### encodeFromLngLatArray + +This encodes an array of coordinates in longitude, latitude order into compressed polyline data. +The data can include an optional 3rd dimension when encoding with the `FlexiblePolyline` algorithm. +While this isn't needed for MapLibre rendering, you might need it to compress data for a request +to a Location Service Provider when requesting route-related data. + +```swift +guard let polylineString = try? Polyline.encodeFromLngLatArray(lngLatArray: [[0.0, 0.0], [5.0, 5.0]]) else { + fatalError("error") +} +``` + +### decodeToLineStringFeature + +This is the most common method to use. It decodes compressed polyline data into a GeoJSON +Feature containing a LineString that can directly be used as a MapLibre source for rendering. + +```swift +guard let geoJsonLineStringFeature = try? Polyline.decodeToLineStringFeature(polylineString) else { + fatalError("error") +} +``` + +### decodeToPolygonFeature + +Similar to `decodeToLineStringFeature` it decodes an array of compressed polyline rings into a GeoJSON +Feature containing a Polygon that can directly be used as a MapLibre source for rendering. +This should be used when the compressed data is meant to represent polygon rings, as it will +also generate the correct winding order of the rings for use with GeoJSON. + +```swift +guard let geoJsonPolygonFeature = try? Polyline.decodeToPolygonFeature([polylineString]) else { + fatalError("error") +} +``` + +### decodeToLineString + +This decodes a compressed polyline into a GeoJSON LineString. The LineString can be embedded into the `geometry` +section of a GeoJSON Feature which can then be rendered with MapLibre. + +```swift +guard let geoJsonLineString = try? Polyline.decodeToLineString(polylineString) else { + fatalError("error") +} +``` + +### decodeToPolygon + +This decodes an array of compressed polyline rings into a GeoJSON Polygon. The Polygon can be embedded into the +`geometry` section of a GeoJSON Feature which can then be rendered with MapLibre. + +```swift +guard let geoJsonPolygon = try? Polyline.decodeToPolygon([polylineString]) else { + fatalError("error") +} +``` + +### decodeToLngLatArray + +This decodes compressed polyline data into an array of coordinates in longitude, latitude order. +This method is helpful when you need to directly work with the coordinate data. + +```swift +guard let lngLatArray = try? Polyline.decodeToLngLatArray(polylineString) else { + fatalError("error") +} +``` + +## Security + +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. + +## Getting Help + +The best way to interact with our team is through GitHub. +You can [open an issue](https://github.com/aws-geospatial/polyline/issues/new/choose) and choose from one of our templates for +[bug reports](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=bug%2C+needs-triage&template=---bug-report.md&title=) or +[feature requests](https://github.com/aws-geospatial/polyline/issues/new?assignees=&labels=feature-request&template=---feature-request.md&title=). +If you have a support plan with [AWS Support](https://aws.amazon.com/premiumsupport/), you can also create a new support case. + +## Contributing + +We welcome community contributions and pull requests. See [CONTRIBUTING](CONTRIBUTING.md) for information on how to set up a development environment and submit code. + +## License + +This library is licensed under the MIT-0 License. See the [LICENSE](LICENSE) file.