Skip to content

Conversation

@dkhawk
Copy link
Contributor

@dkhawk dkhawk commented Aug 20, 2025

This commit introduces a significant modernization of the PolyUtil class by porting it from Java to idiomatic Kotlin. This change improves the code's conciseness, readability, and null safety.

The key changes in this commit are:

  • Porting PolyUtil to Kotlin: The PolyUtil class has been completely rewritten in Kotlin, taking advantage of features like top-level functions, default arguments, and extension functions. The public API has been preserved with @JvmStatic annotations to ensure backward compatibility for Java consumers.
  • Updating tests to use Google Truth: The corresponding PolyUtilTest has been updated to use Google Truth assertions. This makes the tests more readable and expressive.

dkhawk added 3 commits August 20, 2025 07:28
This commit ports the `MathUtil` class from Java to idiomatic Kotlin.

The existing tests were leveraged to ensure that the port was successful, and a new test was added for `MathUtil` to ensure that it is well-tested.
This commit ports the `SphericalUtil` class from Java to idiomatic Kotlin.

The existing tests were leveraged to ensure that the port was successful, and the tests were updated to use Google Truth assertions.
This commit introduces a significant modernization of the `PolyUtil` class by porting it from Java to idiomatic Kotlin. This change improves the code's conciseness, readability, and null safety.

The key changes in this commit are:
- **Porting `PolyUtil` to Kotlin**: The `PolyUtil` class has been completely rewritten in Kotlin, taking advantage of features like top-level functions, default arguments, and extension functions. The public API has been preserved with `@JvmStatic` annotations to ensure backward compatibility for Java consumers.
- **Updating tests to use Google Truth**: The corresponding `PolyUtilTest` has been updated to use Google Truth assertions. This makes the tests more readable and expressive.
@dkhawk dkhawk requested a review from kikoso August 20, 2025 15:48
@googlemaps-bot
Copy link
Contributor

googlemaps-bot commented Aug 20, 2025

Code Coverage

Overall Project 36.26% -0.13% 🍏
Files changed 98.52% 🍏

File Coverage
MathUtil.kt 100% 🍏
SphericalUtil.kt 99.69% -0.31% 🍏
PolyUtil.kt 97.93% -2.07% 🍏

Copy link
Collaborator

@kikoso kikoso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good! One thought is if we want to incorporate at this point a wrapper for LatLng, but it can be introduced when more classes are migrated.

@dkhawk dkhawk merged commit 90c56df into main Aug 26, 2025
10 checks passed
@dkhawk dkhawk deleted the feat/kotlin-port branch August 26, 2025 16:07
googlemaps-bot pushed a commit that referenced this pull request Aug 26, 2025
# [3.16.0](v3.15.0...v3.16.0) (2025-08-26)

### Features

* **library:** Port PolyUtil to Kotlin and enhance tests ([#1565](#1565)) ([90c56df](90c56df))
@googlemaps-bot
Copy link
Contributor

🎉 This PR is included in version 3.16.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@googlemaps-bot
Copy link
Contributor

🎉 This PR is included in version 3.16.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

1 similar comment
@googlemaps-bot
Copy link
Contributor

🎉 This PR is included in version 3.16.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

* using either geodesic (great circle) or rhumb (loxodromic) paths.
*/
object PolyUtil {
private const val DEFAULT_TOLERANCE = 0.1 // meters

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dkhawk DEFAULT_TOLERANCE used to be public API, now it's private. Unintentional breaking change?

public static final double DEFAULT_TOLERANCE = 0.1; // meters.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bubenheimer, apologies for the delay. This should have been marked, in fact, as a breaking change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @kikoso, I wish there was some documentation why 0.1 as a default on various APIs in this and related libs, rather than a seemingly arbitrary constant.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bubenheimer , 0.1 is generally used as a de facto tolerance value when using the Douglas-Peucker algorithm, which is the one used in the Polyline. Agree, this should be clarified in the documentation

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that is a good rationale!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kikoso At the same time, in my opinion, if it is a commonly used constant with that algorithm, then it is meaningful for this API, and should remain a part of the public API, not just some default value. For example, in my case, I try to use accuracy of device location as the tolerance value for some of these APIs, but when accuracy is unavailable, I need to default to something else, i.e. the 0.1 constant, now with an added comment, rather than call the method with a different signature to automatically get the default, which is even more obscure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to that, it appears the DEFAULT_TOLERANCE constant isn't actually used by the Douglas-Peucker implementation unless it's explicitly passed in.

This isn't a new change with the Kotlin port; the previous Java implementation had the same behavior (see PolyUtil.java): https://github.com/googlemaps/android-maps-utils/blob/0bb1d348290ee02c74c02fef13e0e560b4bd370f/library/src/main/java/com/google/maps/android/PolyUtil.java

The current simplify() method still requires the tolerance as an argument, so users would only be using that 0.1 value if they were passing DEFAULT_TOLERANCE in manually. The tolerance value is the primary lever for simplification and is highly use-case-dependent.

Low Tolerance (e.g., 0.1): In my testing, this was often overkill and didn't provide a meaningful reduction in points.

Higher Tolerance (e.g., 5.0 - 10.0): This offered dramatic point savings. While it does create a noticeable (but often acceptable) change in the polyline's shape, it's very effective for things like GPS track rendering (which often has overly dense location data).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And FWIW, we made the constant public again: #1619

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @dkhawk, for these valuable details, which may come in handy for me in the future. At this time I've been using DEFAULT_TOLERANCE just as a fallback for isLocationOnEdge(), but I did not heavily test it. I should use simplify() as well, though, as I need to constrain polygon complexity for performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants