From 4175a53af69ba850568d739929a95b5f87388fe7 Mon Sep 17 00:00:00 2001 From: Artak Kalantarian Date: Tue, 3 Jan 2023 11:26:07 -0800 Subject: [PATCH] More of the SDK files converted to Kotlin (#646) --- .../mapbox/mapboxsdk/annotations/Polygon.java | 1 + .../mapboxsdk/annotations/PolygonOptions.java | 14 +- .../mapbox/mapboxsdk/camera/CameraPosition.kt | 21 +- .../mapboxsdk/camera/CameraUpdateFactory.kt | 14 +- .../com/mapbox/mapboxsdk/geometry/LatLng.java | 335 ---------- .../com/mapbox/mapboxsdk/geometry/LatLng.kt | 306 +++++++++ .../mapboxsdk/geometry/LatLngBounds.java | 610 ------------------ .../mapbox/mapboxsdk/geometry/LatLngBounds.kt | 508 +++++++++++++++ .../mapbox/mapboxsdk/geometry/LatLngQuad.java | 95 --- .../mapbox/mapboxsdk/geometry/LatLngQuad.kt | 74 +++ .../mapbox/mapboxsdk/geometry/LatLngSpan.java | 140 ---- .../mapbox/mapboxsdk/geometry/LatLngSpan.kt | 115 ++++ .../{package-info.java => PackageInfo.kt} | 2 +- .../mapboxsdk/geometry/ProjectedMeters.java | 156 ----- .../mapboxsdk/geometry/ProjectedMeters.kt | 142 ++++ .../mapboxsdk/geometry/VisibleRegion.java | 162 ----- .../mapboxsdk/geometry/VisibleRegion.kt | 159 +++++ .../com/mapbox/mapboxsdk/utils/Extensions.kt | 7 + .../mapbox/mapboxsdk/lint/KeepDetectorTest.kt | 8 +- .../activity/annotation/BulkMarkerActivity.kt | 22 +- .../activity/camera/CameraAnimatorActivity.kt | 6 +- .../location/LocationFragmentActivity.kt | 6 +- .../style/AnimatedSymbolLayerActivity.kt | 33 +- .../PerformanceMeasurementActivity.java | 9 +- .../src/main/res/values/strings.xml | 1 + 25 files changed, 1388 insertions(+), 1558 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.kt rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/{package-info.java => PackageInfo.kt} (62%) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.kt create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Extensions.kt diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java index d55081c0b..7ce2c64bd 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java @@ -55,6 +55,7 @@ public final class Polygon extends BasePointCollection { * * @return A {@link List} of {@link List} of {@link LatLng} points making up the holes. */ + @NonNull public List> getHoles() { return new ArrayList<>(holes); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java index e89ef7576..3e4c3803e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java @@ -239,6 +239,7 @@ public final class PolygonOptions implements Parcelable { * * @return The list made up of {@link LatLng} points defining the polygon. */ + @NonNull public List getPoints() { // the getter gives us a copy, which is the safe thing to do... return polygon.getPoints(); @@ -249,6 +250,7 @@ public final class PolygonOptions implements Parcelable { * * @return The list made up of {@link List} of {@link List} of {@link LatLng} points defining the holes. */ + @NonNull public List> getHoles() { return polygon.getHoles(); } @@ -276,16 +278,20 @@ public final class PolygonOptions implements Parcelable { if (Float.compare(polygon.getAlpha(), getAlpha()) != 0) { return false; } + if (getFillColor() != polygon.getFillColor()) { return false; } + if (getStrokeColor() != polygon.getStrokeColor()) { return false; } - if (getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null) { + + if (!getPoints().equals(polygon.getPoints())) { return false; } - return !(getHoles() != null ? !getHoles().equals(polygon.getHoles()) : polygon.getHoles() != null); + + return getHoles().equals(polygon.getHoles()); } /** @@ -302,8 +308,8 @@ public final class PolygonOptions implements Parcelable { result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0); result = 31 * result + getFillColor(); result = 31 * result + getStrokeColor(); - result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0); - result = 31 * result + (getHoles() != null ? getHoles().hashCode() : 0); + result = 31 * result + getPoints().hashCode(); + result = 31 * result + getHoles().hashCode(); return result; } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.kt index 0f769de02..cef0f0c69 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.kt +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.kt @@ -1,6 +1,7 @@ package com.mapbox.mapboxsdk.camera import android.content.res.TypedArray +import android.os.Build import android.os.Parcel import android.os.Parcelable import androidx.annotation.FloatRange @@ -363,17 +364,23 @@ class CameraPosition @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(`in`: Parcel): CameraPosition { - val bearing = `in`.readDouble() - val target = `in`.readParcelable(LatLng::class.java.classLoader) - val tilt = `in`.readDouble() - val zoom = `in`.readDouble() + override fun createFromParcel(parcel: Parcel): CameraPosition { + val bearing = parcel.readDouble() + + @Suppress("DEPRECATION") + val target = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + parcel.readParcelable(LatLng::class.java.classLoader, LatLng::class.java) + } else { + parcel.readParcelable(LatLng::class.java.classLoader) + } + val tilt = parcel.readDouble() + val zoom = parcel.readDouble() var padding: DoubleArray? = null - val paddingSize = `in`.readInt() + val paddingSize = parcel.readInt() if (paddingSize > 0) { padding = DoubleArray(paddingSize) for (i in 0 until paddingSize) { - padding[i] = `in`.readDouble() + padding[i] = parcel.readDouble() } } return CameraPosition(target, zoom, tilt, bearing, padding) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.kt index ea7aa9661..3c7a00132 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.kt +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.kt @@ -361,10 +361,14 @@ object CameraUpdateFactory { } override fun toString(): String { - return ("CameraBoundsUpdate{" + "bounds=" + bounds + ", padding=" + Arrays.toString(padding) + '}') + return ("CameraBoundsUpdate{" + "bounds=" + bounds + ", padding=" + padding.contentToString() + '}') } } + /* This class 1. Does not seem to be used 2. The code that calculates targetPoint seems to be a bit suspicious. + commenting out for now. + */ + /* internal class CameraMoveUpdate(private val x: Float, private val y: Float) : CameraUpdate { override fun getCameraPosition(mapboxMap: MapboxMap): CameraPosition { val uiSettings = mapboxMap.uiSettings @@ -372,10 +376,11 @@ object CameraUpdateFactory { // Calculate the new center point val viewPortWidth = uiSettings.width val viewPortHeight = uiSettings.height - val padding = mapboxMap.padding + val padding = mapboxMap.cameraPosition.padding!! - // we inverse the map padding, is reapplied when using moveTo/easeTo or animateTo - val targetPoint = PointF((viewPortWidth - padding[0] + padding[1]) / 2 + x, (viewPortHeight + padding[1] - padding[3]) / 2 + y) + // we inverse the map padding, is reapplied when using moveTo/easeTo or animateTo + val targetPoint = PointF((viewPortWidth - padding[0].toFloat() + padding[1].toFloat()) / 2 + x, + (viewPortHeight + padding[1].toFloat() - padding[3].toFloat()) / 2 + y) val latLng = projection.fromScreenLocation(targetPoint) val previousPosition = mapboxMap.cameraPosition return CameraPosition.Builder().target(latLng).zoom(previousPosition.zoom).tilt(previousPosition.tilt).bearing(previousPosition.bearing).build() @@ -406,6 +411,7 @@ object CameraUpdateFactory { return ("CameraMoveUpdate{" + "x=" + x + ", y=" + y + '}') } } + */ class ZoomUpdate : CameraUpdate { @IntDef(ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java deleted file mode 100644 index 04609810c..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.location.Location; -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.FloatRange; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.mapbox.geojson.Point; -import com.mapbox.mapboxsdk.constants.GeometryConstants; -import com.mapbox.turf.TurfMeasurement; - -import static com.mapbox.turf.TurfConstants.UNIT_METRES; - - -/** - * A geographical location which contains a single latitude, longitude pair, with - * optional altitude. - *

- * Latitude and longitude are expressed as decimal degrees - * in the WGS84 datum. By default, altitude is 0.0, or sea level. - *

- *

- * Mapbox GL displays maps in the Mercator Projection and projects geographical - * data automatically, so all data enters in the WGS84 datum. - *

- */ -public class LatLng implements Parcelable { - - /** - * Inner class responsible for recreating Parcels into objects. - */ - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public LatLng createFromParcel(@NonNull Parcel in) { - return new LatLng(in); - } - - public LatLng[] newArray(int size) { - return new LatLng[size]; - } - }; - - @Keep - private double latitude; - @Keep - private double longitude; - private double altitude = 0.0; - - /** - * Construct a new latitude, longitude point at (0, 0) - */ - public LatLng() { - this.latitude = 0.0; - this.longitude = 0.0; - } - - /** - * Construct a new latitude, longitude point given double arguments - * - * @param latitude Latitude in degrees - * @param longitude Longitude in degrees - */ - @Keep - public LatLng(double latitude, double longitude) { - setLatitude(latitude); - setLongitude(longitude); - } - - /** - * Construct a new latitude, longitude, altitude point given double arguments - * - * @param latitude Latitude in degrees - * @param longitude Longitude in degress - * @param altitude Altitude in meters - */ - public LatLng(double latitude, double longitude, double altitude) { - setLatitude(latitude); - setLongitude(longitude); - setAltitude(altitude); - } - - /** - * Construct a new latitude, longitude, altitude point given location argument - * - * @param location Android Location - */ - public LatLng(Location location) { - this(location.getLatitude(), location.getLongitude(), location.getAltitude()); - } - - /** - * Construct a new latitude, longitude, altitude point given another latitude, longitude, altitude point. - * - * @param latLng LatLng to be cloned. - */ - public LatLng(LatLng latLng) { - this.latitude = latLng.latitude; - this.longitude = latLng.longitude; - this.altitude = latLng.altitude; - } - - /** - * Constructs a new latitude, longitude, altitude tuple given a parcel. - * - * @param in the parcel containing the latitude, longitude, altitude values - */ - protected LatLng(Parcel in) { - setLatitude(in.readDouble()); - setLongitude(in.readDouble()); - setAltitude(in.readDouble()); - } - - /** - * Set the latitude, in degrees. - *

- * This value is in the range of [-90, 90], see {@link GeometryConstants#MIN_LATITUDE} and - * {@link GeometryConstants#MAX_LATITUDE} - *

- * - * @param latitude the latitude value in degrees - * @see GeometryConstants#MIN_LATITUDE - * @see GeometryConstants#MAX_LATITUDE - */ - public void setLatitude( - @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double latitude) { - if (Double.isNaN(latitude)) { - throw new IllegalArgumentException("latitude must not be NaN"); - } - if (Math.abs(latitude) > GeometryConstants.MAX_LATITUDE) { - throw new IllegalArgumentException("latitude must be between -90 and 90"); - } - this.latitude = latitude; - } - - /** - * Get the latitude, in degrees. - *

- * This value is in the range of [-90, 90], see {@link GeometryConstants#MIN_LATITUDE} and - * {@link GeometryConstants#MAX_LATITUDE} - *

- * - * @return the latitude value in degrees - * @see GeometryConstants#MIN_LATITUDE - * @see GeometryConstants#MAX_LATITUDE - */ - public double getLatitude() { - return latitude; - } - - /** - * Set the longitude, in degrees. - *

- * This value is in the range of [-180, 180], see {@link GeometryConstants#MIN_LONGITUDE} and - * {@link GeometryConstants#MAX_LONGITUDE} - *

- * - * @param longitude the longitude value in degrees - * @see GeometryConstants#MIN_LONGITUDE - * @see GeometryConstants#MAX_LONGITUDE - */ - public void setLongitude(@FloatRange(from = GeometryConstants.MIN_LONGITUDE, to = GeometryConstants.MAX_LONGITUDE) - double longitude) { - if (Double.isNaN(longitude)) { - throw new IllegalArgumentException("longitude must not be NaN"); - } - if (Double.isInfinite(longitude)) { - throw new IllegalArgumentException("longitude must not be infinite"); - } - this.longitude = longitude; - } - - /** - * Get the longitude, in degrees. - *

- * This value is in the range of [-180, 180], see {@link GeometryConstants#MIN_LONGITUDE} and - * {@link GeometryConstants#MAX_LONGITUDE} - *

- * - * @return the longitude value in degrees - * @see GeometryConstants#MIN_LONGITUDE - * @see GeometryConstants#MAX_LONGITUDE - */ - public double getLongitude() { - return longitude; - } - - /** - * Set the altitude, in meters. - * - * @param altitude the altitude in meters - */ - public void setAltitude(double altitude) { - this.altitude = altitude; - } - - /** - * Get the altitude, in meters. - * - * @return the altitude value in meters - */ - public double getAltitude() { - return altitude; - } - - /** - * Return a new LatLng object with a wrapped Longitude. This allows original data object - * to remain unchanged. - * - * @return new LatLng object with wrapped Longitude - */ - @NonNull - public LatLng wrap() { - return new LatLng(latitude, wrap(longitude, - GeometryConstants.MIN_WRAP_LONGITUDE, GeometryConstants.MAX_WRAP_LONGITUDE) - ); - } - - - /** - * Constrains value to the given range (including min & max) via modular arithmetic. - *

- * Same formula as used in Core GL (wrap.hpp) - * std::fmod((std::fmod((value - min), d) + d), d) + min; - *

- *

- * Multiples of max value will be wrapped to max. - *

- * - * @param value Value to wrap - * @param min Minimum value - * @param max Maximum value - * @return Wrapped value - */ - static double wrap(double value, double min, double max) { - double delta = max - min; - - double firstMod = (value - min) % delta; - double secondMod = (firstMod + delta) % delta; - - if (value >= max && secondMod == 0) { - return max; - } - return secondMod + min; - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param object The object to compare - * @return True if equal, false if not - */ - @Override - public boolean equals(@Nullable Object object) { - if (this == object) { - return true; - } - if (object == null || getClass() != object.getClass()) { - return false; - } - - LatLng latLng = (LatLng) object; - - return Double.compare(latLng.altitude, altitude) == 0 && Double.compare(latLng.latitude, latitude) == 0 - && Double.compare(latLng.longitude, longitude) == 0; - } - - /** - * Returns a hash code value for the object. - * - * @return the hash code value - */ - @Override - public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(latitude); - result = (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(longitude); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(altitude); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - /** - * Returns a string representation of the object. - * - * @return the string representation - */ - @NonNull - @Override - public String toString() { - return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]"; - } - - /** - * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. - * - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written - */ - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeDouble(latitude); - out.writeDouble(longitude); - out.writeDouble(altitude); - } - - /** - * Calculate distance between two points - * - * @param other Other LatLng to compare to - * @return distance in meters - */ - public double distanceTo(@NonNull LatLng other) { - return TurfMeasurement.distance( - Point.fromLngLat(longitude, latitude), - Point.fromLngLat(other.getLongitude(), other.getLatitude()), - UNIT_METRES - ); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.kt new file mode 100644 index 000000000..725f23b85 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.kt @@ -0,0 +1,306 @@ +package com.mapbox.mapboxsdk.geometry + +import android.location.Location +import android.os.Parcel +import android.os.Parcelable +import androidx.annotation.FloatRange +import androidx.annotation.Keep +import com.mapbox.geojson.Point +import com.mapbox.mapboxsdk.constants.GeometryConstants +import com.mapbox.turf.TurfConstants +import com.mapbox.turf.TurfMeasurement + +/** + * A geographical location which contains a single latitude, longitude pair, with + * optional altitude. + * + * + * Latitude and longitude are expressed as decimal degrees + * in the WGS84 datum. By default, altitude is 0.0, or sea level. + * + * + * + * Mapbox GL displays maps in the Mercator Projection and projects geographical + * data automatically, so all data enters in the WGS84 datum. + * + */ +class LatLng : Parcelable { + /** + * Get the latitude, in degrees. + * + * + * This value is in the range of [-90, 90], see [GeometryConstants.MIN_LATITUDE] and + * [GeometryConstants.MAX_LATITUDE] + * + * + * @return the latitude value in degrees + * @see GeometryConstants.MIN_LATITUDE + * + * @see GeometryConstants.MAX_LATITUDE + */ + @Keep + var latitude = 0.0 + private set + + /** + * Get the longitude, in degrees. + * + * + * This value is in the range of [-180, 180], see [GeometryConstants.MIN_LONGITUDE] and + * [GeometryConstants.MAX_LONGITUDE] + * + * + * @return the longitude value in degrees + * @see GeometryConstants.MIN_LONGITUDE + * + * @see GeometryConstants.MAX_LONGITUDE + */ + @Keep + var longitude = 0.0 + private set + + /** + * Get the altitude, in meters. + * + * @return the altitude value in meters + */ + /** + * Set the altitude, in meters. + * + * @var altitude the altitude in meters + */ + var altitude = 0.0 + + /** + * Construct a new latitude, longitude point at (0, 0) + */ + constructor() { + latitude = 0.0 + longitude = 0.0 + } + + /** + * Construct a new latitude, longitude point given double arguments + * + * @param latitude Latitude in degrees + * @param longitude Longitude in degrees + */ + @Keep + constructor(latitude: Double, longitude: Double) { + setLatitude(latitude) + setLongitude(longitude) + } + + /** + * Construct a new latitude, longitude, altitude point given double arguments + * + * @param latitude Latitude in degrees + * @param longitude Longitude in degress + * @param altitude Altitude in meters + */ + constructor(latitude: Double, longitude: Double, altitude: Double) { + setLatitude(latitude) + setLongitude(longitude) + this.altitude = altitude + } + + /** + * Construct a new latitude, longitude, altitude point given location argument + * + * @param location Android Location + */ + constructor(location: Location) : this(location.latitude, location.longitude, location.altitude) {} + + /** + * Construct a new latitude, longitude, altitude point given another latitude, longitude, altitude point. + * + * @param latLng LatLng to be cloned. + */ + constructor(latLng: LatLng) { + latitude = latLng.latitude + longitude = latLng.longitude + altitude = latLng.altitude + } + + /** + * Constructs a new latitude, longitude, altitude tuple given a parcel. + * + * @param in the parcel containing the latitude, longitude, altitude values + */ + constructor(`in`: Parcel) { + setLatitude(`in`.readDouble()) + setLongitude(`in`.readDouble()) + altitude = `in`.readDouble() + } + + /** + * Set the latitude, in degrees. + * + * + * This value is in the range of [-90, 90], see [GeometryConstants.MIN_LATITUDE] and + * [GeometryConstants.MAX_LATITUDE] + * + * + * @param latitude the latitude value in degrees + * @see GeometryConstants.MIN_LATITUDE + * + * @see GeometryConstants.MAX_LATITUDE + */ + fun setLatitude( + @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latitude: Double + ) { + require(!latitude.isNaN()) { "latitude must not be NaN" } + require(Math.abs(latitude) <= GeometryConstants.MAX_LATITUDE) { "latitude must be between -90 and 90" } + this.latitude = latitude + } + + /** + * Set the longitude, in degrees. + * + * + * This value is in the range of [-180, 180], see [GeometryConstants.MIN_LONGITUDE] and + * [GeometryConstants.MAX_LONGITUDE] + * + * + * @param longitude the longitude value in degrees + * @see GeometryConstants.MIN_LONGITUDE + * + * @see GeometryConstants.MAX_LONGITUDE + */ + fun setLongitude(@FloatRange(from = GeometryConstants.MIN_LONGITUDE, to = GeometryConstants.MAX_LONGITUDE) longitude: Double) { + require(!longitude.isNaN()) { "longitude must not be NaN" } + require(!longitude.isInfinite()) { "longitude must not be infinite" } + this.longitude = longitude + } + + /** + * Return a new LatLng object with a wrapped Longitude. This allows original data object + * to remain unchanged. + * + * @return new LatLng object with wrapped Longitude + */ + fun wrap(): LatLng { + return LatLng( + latitude, + wrap(longitude, GeometryConstants.MIN_WRAP_LONGITUDE, GeometryConstants.MAX_WRAP_LONGITUDE) + ) + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param other The object to compare + * @return True if equal, false if not + */ + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other == null || javaClass != other.javaClass) { + return false + } + val latLng = other as LatLng + return java.lang.Double.compare(latLng.altitude, altitude) == 0 && java.lang.Double.compare(latLng.latitude, latitude) == 0 && java.lang.Double.compare(latLng.longitude, longitude) == 0 + } + + /** + * Returns a hash code value for the object. + * + * @return the hash code value + */ + override fun hashCode(): Int { + var result: Int + var temp: Long + temp = java.lang.Double.doubleToLongBits(latitude) + result = (temp xor (temp ushr 32)).toInt() + temp = java.lang.Double.doubleToLongBits(longitude) + result = 31 * result + (temp xor (temp ushr 32)).toInt() + temp = java.lang.Double.doubleToLongBits(altitude) + result = 31 * result + (temp xor (temp ushr 32)).toInt() + return result + } + + /** + * Returns a string representation of the object. + * + * @return the string representation + */ + override fun toString(): String { + return "LatLng [latitude=$latitude, longitude=$longitude, altitude=$altitude]" + } + + /** + * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. + * + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + override fun describeContents(): Int { + return 0 + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written + */ + override fun writeToParcel(out: Parcel, flags: Int) { + out.writeDouble(latitude) + out.writeDouble(longitude) + out.writeDouble(altitude) + } + + /** + * Calculate distance between two points + * + * @param other Other LatLng to compare to + * @return distance in meters + */ + fun distanceTo(other: LatLng): Double { + return TurfMeasurement.distance(Point.fromLngLat(longitude, latitude), Point.fromLngLat(other.longitude, other.latitude), TurfConstants.UNIT_METRES) + } + + companion object { + /** + * Inner class responsible for recreating Parcels into objects. + */ + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): LatLng { + return LatLng(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + + /** + * Constrains value to the given range (including min & max) via modular arithmetic. + * + * + * Same formula as used in Core GL (wrap.hpp) + * std::fmod((std::fmod((value - min), d) + d), d) + min; + * + * + * + * Multiples of max value will be wrapped to max. + * + * + * @param value Value to wrap + * @param min Minimum value + * @param max Maximum value + * @return Wrapped value + */ + fun wrap(value: Double, min: Double, max: Double): Double { + val delta = max - min + val firstMod = (value - min) % delta + val secondMod = (firstMod + delta) % delta + return if (value >= max && secondMod == 0.0) { + max + } else { + secondMod + min + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java deleted file mode 100644 index 226e0bfba..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java +++ /dev/null @@ -1,610 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.FloatRange; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.mapbox.mapboxsdk.constants.GeometryConstants; -import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException; - -import java.util.ArrayList; -import java.util.List; - -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MAX_LATITUDE; -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MAX_LONGITUDE; -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MAX_WRAP_LONGITUDE; -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MIN_LATITUDE; -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MIN_LONGITUDE; -import static com.mapbox.mapboxsdk.constants.GeometryConstants.MIN_WRAP_LONGITUDE; - -/** - * A geographical area representing a latitude/longitude aligned rectangle. - *

- * This class does not wrap values to the world bounds. - *

- */ -public class LatLngBounds implements Parcelable { - - @Keep - private final double latitudeNorth; - @Keep - private final double latitudeSouth; - @Keep - private final double longitudeEast; - @Keep - private final double longitudeWest; - - /** - * Construct a new LatLngBounds based on its corners, given in NESW - * order. - *

- * @since 7.0.0 LatLngBounds cannot be wrapped any more, i.e longitudeWest has to be - * less or equal to longitudeEast. - * - * For example, to represent bounds spanning 20 degrees crossing antimeridian with - * the NE point as (10, -170) and the SW point as (-10, 170), - * use (10, -190) and (-10, -170), or (10, -170) and (-10, -150). - * - * @param northLatitude Northern Latitude - * @param eastLongitude Eastern Longitude - * @param southLatitude Southern Latitude - * @param westLongitude Western Longitude - */ - @Keep - LatLngBounds(final double northLatitude, final double eastLongitude, - final double southLatitude, final double westLongitude) { - this.latitudeNorth = northLatitude; - this.longitudeEast = eastLongitude; - this.latitudeSouth = southLatitude; - this.longitudeWest = westLongitude; - } - - /** - * Returns the world bounds. - * - * @return the bounds representing the world - */ - public static LatLngBounds world() { - return LatLngBounds.from( - MAX_LATITUDE, MAX_WRAP_LONGITUDE, - MIN_LATITUDE, MIN_WRAP_LONGITUDE); - } - - /** - * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns - * it as a point. This is a non-geodesic calculation which is not the geographic center. - * - * @return LatLng center of this LatLngBounds - */ - @NonNull - public LatLng getCenter() { - double latCenter = (this.latitudeNorth + this.latitudeSouth) / 2.0; - double longCenter = (this.longitudeEast + this.longitudeWest) / 2.0; - - return new LatLng(latCenter, longCenter); - } - - /** - * Get the north latitude value of this bounds. - * - * @return double latitude value for north - */ - public double getLatNorth() { - return this.latitudeNorth; - } - - /** - * Get the south latitude value of this bounds. - * - * @return double latitude value for south - */ - public double getLatSouth() { - return this.latitudeSouth; - } - - /** - * Get the east longitude value of this bounds. - * - * @return double longitude value for east - */ - public double getLonEast() { - return this.longitudeEast; - } - - /** - * Get the west longitude value of this bounds. - * - * @return double longitude value for west - */ - public double getLonWest() { - return this.longitudeWest; - } - - /** - * Get the latitude-longitude pair of the south west corner of this bounds. - * - * @return LatLng of the south west corner - */ - @NonNull - public LatLng getSouthWest() { - return new LatLng(latitudeSouth, longitudeWest); - } - - /** - * Get the latitude-longitude paur if the north east corner of this bounds. - * - * @return LatLng of the north east corner - */ - @NonNull - public LatLng getNorthEast() { - return new LatLng(latitudeNorth, longitudeEast); - } - - /** - * Get the latitude-longitude pair of the south east corner of this bounds. - * - * @return LatLng of the south east corner - */ - @NonNull - public LatLng getSouthEast() { - return new LatLng(latitudeSouth, longitudeEast); - } - - /** - * Get the latitude-longitude pair of the north west corner of this bounds. - * - * @return LatLng of the north west corner - */ - @NonNull - public LatLng getNorthWest() { - return new LatLng(latitudeNorth, longitudeWest); - } - - /** - * Get the area spanned by this LatLngBounds - * - * @return LatLngSpan area - */ - @NonNull - public LatLngSpan getSpan() { - return new LatLngSpan(getLatitudeSpan(), getLongitudeSpan()); - } - - /** - * Get the absolute distance, in degrees, between the north and - * south boundaries of this LatLngBounds - * - * @return Span distance - */ - public double getLatitudeSpan() { - return Math.abs(this.latitudeNorth - this.latitudeSouth); - } - - /** - * Get the absolute distance, in degrees, between the west and - * east boundaries of this LatLngBounds - * - * @return Span distance - */ - public double getLongitudeSpan() { - return Math.abs(this.longitudeEast - this.longitudeWest); - } - - /** - * Validate if LatLngBounds is empty, determined if absolute distance is - * - * @return boolean indicating if span is empty - */ - public boolean isEmptySpan() { - return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0; - } - - /** - * Returns a string representaton of the object. - * - * @return the string representation - */ - @NonNull - @Override - public String toString() { - return "N:" + this.latitudeNorth + "; E:" + this.longitudeEast + "; S:" + this.latitudeSouth - + "; W:" + this.longitudeWest; - } - - /** - * Constructs a LatLngBounds that contains all of a list of LatLng - * objects. Empty lists will yield invalid LatLngBounds. - * - * @param latLngs List of LatLng objects - * @return LatLngBounds - */ - static LatLngBounds fromLatLngs(final List latLngs) { - double minLat = MAX_LATITUDE; - double minLon = MAX_LONGITUDE; - double maxLat = MIN_LATITUDE; - double maxLon = MIN_LONGITUDE; - - for (final LatLng gp : latLngs) { - final double latitude = gp.getLatitude(); - final double longitude = gp.getLongitude(); - minLat = Math.min(minLat, latitude); - minLon = Math.min(minLon, longitude); - maxLat = Math.max(maxLat, latitude); - maxLon = Math.max(maxLon, longitude); - } - - return new LatLngBounds(maxLat, maxLon, minLat, minLon); - } - - /** - * Return an array of LatLng objects resembling this bounds. - * - * @return an array of 2 LatLng objects. - */ - @NonNull - public LatLng[] toLatLngs() { - return new LatLng[] {getNorthEast(), getSouthWest()}; - } - - /** - * Constructs a LatLngBounds from doubles representing a LatLng pair. - *

- * This values of latNorth and latSouth should be in the range of [-90, 90], - * see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE}, - * otherwise IllegalArgumentException will be thrown. - * latNorth should be greater or equal latSouth, otherwise IllegalArgumentException will be thrown. - *

- * This method doesn't recalculate most east or most west boundaries. - * Note @since 7.0.0 lonEast and lonWest will NOT be wrapped to be in the range of [-180, 180], - * see {@link GeometryConstants#MIN_LONGITUDE} and {@link GeometryConstants#MAX_LONGITUDE} - * lonEast should be greater or equal lonWest, otherwise IllegalArgumentException will be thrown. - *

- */ - public static LatLngBounds from( - @FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latNorth, - double lonEast, - @FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latSouth, - double lonWest) { - - checkParams(latNorth, lonEast, latSouth, lonWest); - - return new LatLngBounds(latNorth, lonEast, latSouth, lonWest); - } - - private static void checkParams( - @FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latNorth, - double lonEast, - @FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latSouth, - double lonWest) { - - if (Double.isNaN(latNorth) || Double.isNaN(latSouth)) { - throw new IllegalArgumentException("latitude must not be NaN"); - } - - if (Double.isNaN(lonEast) || Double.isNaN(lonWest)) { - throw new IllegalArgumentException("longitude must not be NaN"); - } - - if (Double.isInfinite(lonEast) || Double.isInfinite(lonWest)) { - throw new IllegalArgumentException("longitude must not be infinite"); - } - - if (latNorth > MAX_LATITUDE || latNorth < MIN_LATITUDE - || latSouth > MAX_LATITUDE || latSouth < MIN_LATITUDE) { - throw new IllegalArgumentException("latitude must be between -90 and 90"); - } - - if (latNorth < latSouth) { - throw new IllegalArgumentException("latNorth cannot be less than latSouth"); - } - - if (lonEast < lonWest) { - throw new IllegalArgumentException("lonEast cannot be less than lonWest"); - } - } - - private static double lat_(int z, int y) { - double n = Math.PI - 2.0 * Math.PI * y / Math.pow(2.0, z); - return Math.toDegrees(Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))); - } - - private static double lon_(int z, int x) { - return x / Math.pow(2.0, z) * 360.0 - GeometryConstants.MAX_WRAP_LONGITUDE; - } - - /** - * Constructs a LatLngBounds from a Tile identifier. - *

- * Returned bounds will have latitude in the range of Mercator projection. - * - * @param z Tile zoom level. - * @param x Tile X coordinate. - * @param y Tile Y coordinate. - * @see GeometryConstants#MIN_MERCATOR_LATITUDE - * @see GeometryConstants#MAX_MERCATOR_LATITUDE - */ - public static LatLngBounds from(int z, int x, int y) { - return new LatLngBounds(lat_(z, y), lon_(z, x + 1), lat_(z, y + 1), lon_(z, x)); - } - - /** - * Constructs a LatLngBounds from current bounds with an additional latitude-longitude pair. - * - * @param latLng the latitude lognitude pair to include in the bounds. - * @return the newly constructed bounds - */ - @NonNull - public LatLngBounds include(@NonNull LatLng latLng) { - return new LatLngBounds.Builder() - .include(getNorthEast()) - .include(getSouthWest()) - .include(latLng) - .build(); - } - - /** - * Determines whether this LatLngBounds matches another one via LatLng. - * - * @param o another object - * @return a boolean indicating whether the LatLngBounds are equal - */ - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o instanceof LatLngBounds) { - LatLngBounds other = (LatLngBounds) o; - return latitudeNorth == other.getLatNorth() - && latitudeSouth == other.getLatSouth() - && longitudeEast == other.getLonEast() - && longitudeWest == other.getLonWest(); - } - return false; - } - - - private boolean containsLatitude(final double latitude) { - return (latitude <= this.latitudeNorth) - && (latitude >= this.latitudeSouth); - } - - private boolean containsLongitude(final double longitude) { - return (longitude <= this.longitudeEast) - && (longitude >= this.longitudeWest); - } - - /** - * Determines whether this LatLngBounds contains a point. - * - * @param latLng the point which may be contained - * @return true, if the point is contained within the bounds - */ - public boolean contains(@NonNull final LatLng latLng) { - return containsLatitude(latLng.getLatitude()) - && containsLongitude(latLng.getLongitude()); - } - - /** - * Determines whether this LatLngBounds contains another bounds. - * - * @param other the bounds which may be contained - * @return true, if the bounds is contained within the bounds - */ - public boolean contains(@NonNull final LatLngBounds other) { - return contains(other.getNorthEast()) - && contains(other.getSouthWest()); - } - - /** - * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. - * - * @param bounds LatLngBounds to add - * @return LatLngBounds - */ - @NonNull - public LatLngBounds union(@NonNull LatLngBounds bounds) { - return unionNoParamCheck(bounds.getLatNorth(), bounds.getLonEast(), - bounds.getLatSouth(), bounds.getLonWest()); - } - - /** - * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. - * - *

- * This values of northLat and southLat should be in the range of [-90, 90], - * see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE}, - * otherwise IllegalArgumentException will be thrown. - * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown. - * - *

- * eastLon should be greater or equal westLon, otherwise IllegalArgumentException will be thrown. - * - * @param northLat Northern Latitude corner point - * @param eastLon Eastern Longitude corner point - * @param southLat Southern Latitude corner point - * @param westLon Western Longitude corner point - * @return LatLngBounds - */ - @NonNull - public LatLngBounds union(final double northLat, final double eastLon, - final double southLat, final double westLon) { - checkParams(northLat, eastLon, southLat, westLon); - return unionNoParamCheck(northLat, eastLon, southLat, westLon); - } - - private LatLngBounds unionNoParamCheck(final double northLat, final double eastLon, - final double southLat, final double westLon) { - - return new LatLngBounds((this.latitudeNorth < northLat) ? northLat : this.latitudeNorth, - (this.longitudeEast < eastLon) ? eastLon : this.longitudeEast, - (this.latitudeSouth > southLat) ? southLat : this.latitudeSouth, - (this.longitudeWest > westLon) ? westLon : this.longitudeWest); - } - - /** - * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds, - * - * @param box LatLngBounds to intersect with - * @return LatLngBounds - */ - @Nullable - public LatLngBounds intersect(@NonNull LatLngBounds box) { - return intersectNoParamCheck(box.getLatNorth(), box.getLonEast(), box.getLatSouth(), box.getLonWest()); - } - - - /** - * Returns a new LatLngBounds that is the intersection of this with another box. - * - *

- * This values of northLat and southLat should be in the range of [-90, 90], - * see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE}, - * otherwise IllegalArgumentException will be thrown. - * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown. - * - *

- * eastLon should be greater or equal westLon, otherwise IllegalArgumentException will be thrown. - * - * @param northLat Northern Latitude corner point - * @param eastLon Eastern Longitude corner point - * @param southLat Southern Latitude corner point - * @param westLon Western Longitude corner point - * @return LatLngBounds - */ - @NonNull - public LatLngBounds intersect(final double northLat, final double eastLon, - final double southLat, final double westLon) { - checkParams(northLat, eastLon, southLat, westLon); - return intersectNoParamCheck(northLat, eastLon, southLat, westLon); - } - - private LatLngBounds intersectNoParamCheck(final double northLat, final double eastLon, - final double southLat, final double westLon) { - - double minLonWest = Math.max(this.longitudeWest, westLon); - double maxLonEast = Math.min(this.longitudeEast, eastLon); - if (maxLonEast >= minLonWest) { - double minLatSouth = Math.max(this.latitudeSouth, southLat); - double maxLatNorth = Math.min(this.latitudeNorth, northLat); - if (maxLatNorth >= minLatSouth) { - return new LatLngBounds(maxLatNorth, maxLonEast, minLatSouth, minLonWest); - } - } - return null; - } - - - - /** - * Inner class responsible for recreating Parcels into objects. - */ - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public LatLngBounds createFromParcel(@NonNull final Parcel in) { - return readFromParcel(in); - } - - @Override - public LatLngBounds[] newArray(final int size) { - return new LatLngBounds[size]; - } - }; - - /** - * Returns a hash code value for the object. - * - * @return the hash code - */ - @Override - public int hashCode() { - return (int) ((latitudeNorth + 90) - + ((latitudeSouth + 90) * 1000) - + ((longitudeEast + 180) * 1000000) - + ((longitudeWest + 180) * 1000000000)); - } - - /** - * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. - * - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written - */ - @Override - public void writeToParcel(@NonNull final Parcel out, final int flags) { - out.writeDouble(this.latitudeNorth); - out.writeDouble(this.longitudeEast); - out.writeDouble(this.latitudeSouth); - out.writeDouble(this.longitudeWest); - } - - private static LatLngBounds readFromParcel(final Parcel in) { - final double northLat = in.readDouble(); - final double eastLon = in.readDouble(); - final double southLat = in.readDouble(); - final double westLon = in.readDouble(); - return new LatLngBounds(northLat, eastLon, southLat, westLon); - } - - /** - * Builder for composing LatLngBounds objects. - */ - public static final class Builder { - - private final List latLngList = new ArrayList<>(); - - /** - * Builds a new LatLngBounds. - *

- * Throws an {@link InvalidLatLngBoundsException} when no LatLngBounds can be created. - *

- * - * @return the build LatLngBounds - */ - public LatLngBounds build() { - if (latLngList.size() < 2) { - throw new InvalidLatLngBoundsException(latLngList.size()); - } - return LatLngBounds.fromLatLngs(latLngList); - } - - /** - * Adds a LatLng object to the LatLngBounds.Builder. - * - * @param latLngs the List of LatLng objects to be added - * @return this - */ - @NonNull - public Builder includes(@NonNull List latLngs) { - latLngList.addAll(latLngs); - return this; - } - - /** - * Adds a LatLng object to the LatLngBounds.Builder. - * - * @param latLng the LatLng to be added - * @return this - */ - @NonNull - public Builder include(@NonNull LatLng latLng) { - latLngList.add(latLng); - return this; - } - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.kt new file mode 100644 index 000000000..38a705dbd --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.kt @@ -0,0 +1,508 @@ +package com.mapbox.mapboxsdk.geometry + +import android.os.Parcel +import android.os.Parcelable +import androidx.annotation.FloatRange +import androidx.annotation.Keep +import com.mapbox.mapboxsdk.constants.GeometryConstants +import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException +import com.mapbox.mapboxsdk.utils.isInfinite +import com.mapbox.mapboxsdk.utils.isNaN + +/** + * A geographical area representing a latitude/longitude aligned rectangle. + * + * + * This class does not wrap values to the world bounds. + * + */ +class LatLngBounds +/** + * Construct a new LatLngBounds based on its corners, given in NESW + * order. + * + * + * @since 7.0.0 LatLngBounds cannot be wrapped any more, i.e longitudeWest has to be + * less or equal to longitudeEast. + * + * For example, to represent bounds spanning 20 degrees crossing antimeridian with + * the NE point as (10, -170) and the SW point as (-10, 170), + * use (10, -190) and (-10, -170), or (10, -170) and (-10, -150). + * + * @param latNorth Northern Latitude + * @param lonEast Eastern Longitude + * @param latSouth Southern Latitude + * @param lonWest Western Longitude + */ @Keep internal constructor( + /** + * Get the north latitude value of this bounds. + * + * @return double latitude value for north + */ + @field:Keep val latNorth: Double, + /** + * Get the east longitude value of this bounds. + * + * @return double longitude value for east + */ + @field:Keep val lonEast: Double, + /** + * Get the south latitude value of this bounds. + * + * @return double latitude value for south + */ + @field:Keep val latSouth: Double, + /** + * Get the west longitude value of this bounds. + * + * @return double longitude value for west + */ + @field:Keep val lonWest: Double +) : Parcelable { + + /** + * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns + * it as a point. This is a non-geodesic calculation which is not the geographic center. + * + * @return LatLng center of this LatLngBounds + */ + val center: LatLng + get() { + val latCenter = (latNorth + latSouth) / 2.0 + val longCenter = (lonEast + lonWest) / 2.0 + return LatLng(latCenter, longCenter) + } + + /** + * Get the latitude-longitude pair of the south west corner of this bounds. + * + * @return LatLng of the south west corner + */ + val southWest: LatLng + get() = LatLng(latSouth, lonWest) + + /** + * Get the latitude-longitude paur if the north east corner of this bounds. + * + * @return LatLng of the north east corner + */ + val northEast: LatLng + get() = LatLng(latNorth, lonEast) + + /** + * Get the latitude-longitude pair of the south east corner of this bounds. + * + * @return LatLng of the south east corner + */ + val southEast: LatLng + get() = LatLng(latSouth, lonEast) + + /** + * Get the latitude-longitude pair of the north west corner of this bounds. + * + * @return LatLng of the north west corner + */ + val northWest: LatLng + get() = LatLng(latNorth, lonWest) + + /** + * Get the area spanned by this LatLngBounds + * + * @return LatLngSpan area + */ + val span: LatLngSpan + get() = LatLngSpan(latitudeSpan, longitudeSpan) + + /** + * Get the absolute distance, in degrees, between the north and + * south boundaries of this LatLngBounds + * + * @return Span distance + */ + val latitudeSpan: Double + get() = Math.abs(latNorth - latSouth) + + /** + * Get the absolute distance, in degrees, between the west and + * east boundaries of this LatLngBounds + * + * @return Span distance + */ + val longitudeSpan: Double + get() = Math.abs(lonEast - lonWest) + + /** + * Validate if LatLngBounds is empty, determined if absolute distance is + * + * @return boolean indicating if span is empty + */ + val isEmptySpan: Boolean + get() = longitudeSpan == 0.0 || latitudeSpan == 0.0 + + /** + * Returns a string representaton of the object. + * + * @return the string representation + */ + override fun toString(): String { + return ("N:" + latNorth + "; E:" + lonEast + "; S:" + latSouth + "; W:" + lonWest) + } + + /** + * Return an array of LatLng objects resembling this bounds. + * + * @return an array of 2 LatLng objects. + */ + fun toLatLngs(): Array { + return arrayOf(northEast, southWest) + } + + /** + * Constructs a LatLngBounds from current bounds with an additional latitude-longitude pair. + * + * @param latLng the latitude lognitude pair to include in the bounds. + * @return the newly constructed bounds + */ + fun include(latLng: LatLng): LatLngBounds { + return Builder().include(northEast).include(southWest).include(latLng).build() + } + + /** + * Determines whether this LatLngBounds matches another one via LatLng. + * + * @param other another object + * @return a boolean indicating whether the LatLngBounds are equal + */ + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other is LatLngBounds) { + return latNorth == other.latNorth && latSouth == other.latSouth && lonEast == other.lonEast && lonWest == other.lonWest + } + return false + } + + private fun containsLatitude(latitude: Double): Boolean { + return latitude <= latNorth && latitude >= latSouth + } + + private fun containsLongitude(longitude: Double): Boolean { + return longitude <= lonEast && longitude >= lonWest + } + + /** + * Determines whether this LatLngBounds contains a point. + * + * @param latLng the point which may be contained + * @return true, if the point is contained within the bounds + */ + operator fun contains(latLng: LatLng): Boolean { + return (containsLatitude(latLng.latitude) && containsLongitude(latLng.longitude)) + } + + /** + * Determines whether this LatLngBounds contains another bounds. + * + * @param other the bounds which may be contained + * @return true, if the bounds is contained within the bounds + */ + operator fun contains(other: LatLngBounds): Boolean { + return (contains(other.northEast) && contains(other.southWest)) + } + + /** + * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. + * + * @param bounds LatLngBounds to add + * @return LatLngBounds + */ + fun union(bounds: LatLngBounds): LatLngBounds { + return unionNoParamCheck(bounds.latNorth, bounds.lonEast, bounds.latSouth, bounds.lonWest) + } + + /** + * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. + * + * + * + * This values of northLat and southLat should be in the range of [-90, 90], + * see [GeometryConstants.MIN_LATITUDE] and [GeometryConstants.MAX_LATITUDE], + * otherwise IllegalArgumentException will be thrown. + * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown. + * + * + * + * eastLon should be greater or equal westLon, otherwise IllegalArgumentException will be thrown. + * + * @param northLat Northern Latitude corner point + * @param eastLon Eastern Longitude corner point + * @param southLat Southern Latitude corner point + * @param westLon Western Longitude corner point + * @return LatLngBounds + */ + fun union(northLat: Double, eastLon: Double, southLat: Double, westLon: Double): LatLngBounds { + checkParams(northLat, eastLon, southLat, westLon) + return unionNoParamCheck(northLat, eastLon, southLat, westLon) + } + + private fun unionNoParamCheck(northLat: Double, eastLon: Double, southLat: Double, westLon: Double): LatLngBounds { + return LatLngBounds( + if (latNorth < northLat) northLat else latNorth, + if (lonEast < eastLon) eastLon else lonEast, + if (latSouth > southLat) southLat else latSouth, + if (lonWest > westLon) westLon else lonWest + ) + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds, + * + * @param box LatLngBounds to intersect with + * @return LatLngBounds + */ + fun intersect(box: LatLngBounds): LatLngBounds? { + return intersectNoParamCheck(box.latNorth, box.lonEast, box.latSouth, box.lonWest) + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another box. + * + * + * + * This values of northLat and southLat should be in the range of [-90, 90], + * see [GeometryConstants.MIN_LATITUDE] and [GeometryConstants.MAX_LATITUDE], + * otherwise IllegalArgumentException will be thrown. + * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown. + * + * + * + * eastLon should be greater or equal westLon, otherwise IllegalArgumentException will be thrown. + * + * @param northLat Northern Latitude corner point + * @param eastLon Eastern Longitude corner point + * @param southLat Southern Latitude corner point + * @param westLon Western Longitude corner point + * @return LatLngBounds + */ + fun intersect(northLat: Double, eastLon: Double, southLat: Double, westLon: Double): LatLngBounds { + checkParams(northLat, eastLon, southLat, westLon) + return intersectNoParamCheck(northLat, eastLon, southLat, westLon)!! + } + + private fun intersectNoParamCheck(northLat: Double, eastLon: Double, southLat: Double, westLon: Double): LatLngBounds? { + val minLonWest = Math.max(lonWest, westLon) + val maxLonEast = Math.min(lonEast, eastLon) + if (maxLonEast >= minLonWest) { + val minLatSouth = Math.max(latSouth, southLat) + val maxLatNorth = Math.min(latNorth, northLat) + if (maxLatNorth >= minLatSouth) { + return LatLngBounds(maxLatNorth, maxLonEast, minLatSouth, minLonWest) + } + } + return null + } + + /** + * Returns a hash code value for the object. + * + * @return the hash code + */ + override fun hashCode(): Int { + return (latNorth + 90 + (latSouth + 90) * 1000 + (lonEast + 180) * 1000000 + (lonWest + 180) * 1000000000).toInt() + } + + /** + * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. + * + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + override fun describeContents(): Int { + return 0 + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written + */ + override fun writeToParcel(out: Parcel, flags: Int) { + out.writeDouble(latNorth) + out.writeDouble(lonEast) + out.writeDouble(latSouth) + out.writeDouble(lonWest) + } + + /** + * Builder for composing LatLngBounds objects. + */ + class Builder { + private val latLngList: MutableList = ArrayList() + + /** + * Builds a new LatLngBounds. + * + * + * Throws an [InvalidLatLngBoundsException] when no LatLngBounds can be created. + * + * + * @return the build LatLngBounds + */ + fun build(): LatLngBounds { + if (latLngList.size < 2) { + throw InvalidLatLngBoundsException(latLngList.size) + } + return fromLatLngs(latLngList) + } + + /** + * Adds a LatLng object to the LatLngBounds.Builder. + * + * @param latLngs the List of LatLng objects to be added + * @return this + */ + fun includes(latLngs: List): Builder { + latLngList.addAll(latLngs) + return this + } + + /** + * Adds a LatLng object to the LatLngBounds.Builder. + * + * @param latLng the LatLng to be added + * @return this + */ + fun include(latLng: LatLng): Builder { + latLngList.add(latLng) + return this + } + } + + companion object { + /** + * Returns the world bounds. + * + * @return the bounds representing the world + */ + @JvmStatic + fun world(): LatLngBounds { + return from(GeometryConstants.MAX_LATITUDE, GeometryConstants.MAX_WRAP_LONGITUDE, GeometryConstants.MIN_LATITUDE, GeometryConstants.MIN_WRAP_LONGITUDE) + } + + /** + * Constructs a LatLngBounds that contains all of a list of LatLng + * objects. Empty lists will yield invalid LatLngBounds. + * + * @param latLngs List of LatLng objects + * @return LatLngBounds + */ + fun fromLatLngs(latLngs: List): LatLngBounds { + var minLat = GeometryConstants.MAX_LATITUDE + var minLon = GeometryConstants.MAX_LONGITUDE + var maxLat = GeometryConstants.MIN_LATITUDE + var maxLon = GeometryConstants.MIN_LONGITUDE + for (gp in latLngs) { + val latitude = gp.latitude + val longitude = gp.longitude + minLat = Math.min(minLat, latitude) + minLon = Math.min(minLon, longitude) + maxLat = Math.max(maxLat, latitude) + maxLon = Math.max(maxLon, longitude) + } + return LatLngBounds(maxLat, maxLon, minLat, minLon) + } + + /** + * Constructs a LatLngBounds from doubles representing a LatLng pair. + * + * + * This values of latNorth and latSouth should be in the range of [-90, 90], + * see [GeometryConstants.MIN_LATITUDE] and [GeometryConstants.MAX_LATITUDE], + * otherwise IllegalArgumentException will be thrown. + * latNorth should be greater or equal latSouth, otherwise IllegalArgumentException will be thrown. + * + * + * This method doesn't recalculate most east or most west boundaries. + * Note @since 7.0.0 lonEast and lonWest will NOT be wrapped to be in the range of [-180, 180], + * see [GeometryConstants.MIN_LONGITUDE] and [GeometryConstants.MAX_LONGITUDE] + * lonEast should be greater or equal lonWest, otherwise IllegalArgumentException will be thrown. + * + */ + @JvmStatic + fun from( + @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latNorth: Double, + lonEast: Double, + @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latSouth: Double, + lonWest: Double + ): LatLngBounds { + checkParams(latNorth, lonEast, latSouth, lonWest) + return LatLngBounds(latNorth, lonEast, latSouth, lonWest) + } + + private fun checkParams( + @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latNorth: Double, + lonEast: Double, + @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latSouth: Double, + lonWest: Double + ) { + require(!(Double.isNaN(latNorth) || Double.isNaN(latSouth))) { "latitude must not be NaN" } + require(!(Double.isNaN(lonEast) || Double.isNaN(lonWest))) { "longitude must not be NaN" } + require(!(Double.isInfinite(lonEast) || Double.isInfinite(lonWest))) { "longitude must not be infinite" } + require( + !(latNorth > GeometryConstants.MAX_LATITUDE || latNorth < GeometryConstants.MIN_LATITUDE || latSouth > GeometryConstants.MAX_LATITUDE || latSouth < GeometryConstants.MIN_LATITUDE) + ) { "latitude must be between -90 and 90" } + require(latNorth >= latSouth) { "latNorth cannot be less than latSouth" } + require(lonEast >= lonWest) { "lonEast cannot be less than lonWest" } + } + + private fun lat_(z: Int, y: Int): Double { + val n = Math.PI - 2.0 * Math.PI * y / Math.pow(2.0, z.toDouble()) + return Math.toDegrees(Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))) + } + + private fun lon_(z: Int, x: Int): Double { + return x / Math.pow(2.0, z.toDouble()) * 360.0 - GeometryConstants.MAX_WRAP_LONGITUDE + } + + /** + * Constructs a LatLngBounds from a Tile identifier. + * + * + * Returned bounds will have latitude in the range of Mercator projection. + * + * @param z Tile zoom level. + * @param x Tile X coordinate. + * @param y Tile Y coordinate. + * @see GeometryConstants.MIN_MERCATOR_LATITUDE + * + * @see GeometryConstants.MAX_MERCATOR_LATITUDE + */ + @JvmStatic + fun from(z: Int, x: Int, y: Int): LatLngBounds { + return LatLngBounds(lat_(z, y), lon_(z, x + 1), lat_(z, y + 1), lon_(z, x)) + } + + /** + * Inner class responsible for recreating Parcels into objects. + */ + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): LatLngBounds { + return readFromParcel(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + + private fun readFromParcel(parcel: Parcel): LatLngBounds { + val northLat = parcel.readDouble() + val eastLon = parcel.readDouble() + val southLat = parcel.readDouble() + val westLon = parcel.readDouble() + return LatLngBounds(northLat, eastLon, southLat, westLon) + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.java deleted file mode 100644 index f6f7fd6c1..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; - -/** - * A geographical area representing a non-aligned quadrilateral - *

- * This class does not wrap values to the world bounds - *

- */ -public class LatLngQuad implements Parcelable { - - @Keep - private final LatLng topLeft; - @Keep - private final LatLng topRight; - @Keep - private final LatLng bottomRight; - @Keep - private final LatLng bottomLeft; - - /** - * Construct a new LatLngQuad based on its corners, - * in order top left, top right, bottom left, bottom right - */ - @Keep - public LatLngQuad(final LatLng topLeft, final LatLng topRight, final LatLng bottomRight, final LatLng bottomLeft) { - this.topLeft = topLeft; - this.topRight = topRight; - this.bottomRight = bottomRight; - this.bottomLeft = bottomLeft; - } - - public LatLng getTopLeft() { - return this.topLeft; - } - - public LatLng getTopRight() { - return this.topRight; - } - - public LatLng getBottomRight() { - return this.bottomRight; - } - - public LatLng getBottomLeft() { - return this.bottomLeft; - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public LatLngQuad createFromParcel(@NonNull final Parcel in) { - return readFromParcel(in); - } - - @Override - public LatLngQuad[] newArray(final int size) { - return new LatLngQuad[size]; - } - }; - - @Override - public int hashCode() { - int code = topLeft.hashCode(); - code = (code ^ code >>> 31) + topRight.hashCode(); - code = (code ^ code >>> 31) + bottomRight.hashCode(); - code = (code ^ code >>> 31) + bottomLeft.hashCode(); - return code; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull final Parcel out, final int arg1) { - topLeft.writeToParcel(out, arg1); - topRight.writeToParcel(out, arg1); - bottomRight.writeToParcel(out, arg1); - bottomLeft.writeToParcel(out, arg1); - } - - private static LatLngQuad readFromParcel(@NonNull final Parcel in) { - final LatLng topLeft = new LatLng(in); - final LatLng topRight = new LatLng(in); - final LatLng bottomRight = new LatLng(in); - final LatLng bottomLeft = new LatLng(in); - return new LatLngQuad(topLeft, topRight, bottomRight, bottomLeft); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.kt new file mode 100644 index 000000000..75dbcc908 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngQuad.kt @@ -0,0 +1,74 @@ +package com.mapbox.mapboxsdk.geometry + +import android.os.Parcel +import android.os.Parcelable +import androidx.annotation.Keep + +/** + * A geographical area representing a non-aligned quadrilateral + * + * + * This class does not wrap values to the world bounds + * + */ +class LatLngQuad +/** + * Construct a new LatLngQuad based on its corners, + * in order top left, top right, bottom left, bottom right + */ +@Keep constructor(@field:Keep val topLeft: LatLng, @field:Keep val topRight: LatLng, @field:Keep val bottomRight: LatLng, @field:Keep val bottomLeft: LatLng) : Parcelable { + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(out: Parcel, arg1: Int) { + topLeft.writeToParcel(out, arg1) + topRight.writeToParcel(out, arg1) + bottomRight.writeToParcel(out, arg1) + bottomLeft.writeToParcel(out, arg1) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as LatLngQuad + + if (topLeft != other.topLeft) return false + if (topRight != other.topRight) return false + if (bottomRight != other.bottomRight) return false + if (bottomLeft != other.bottomLeft) return false + + return true + } + + override fun hashCode(): Int { + var result = topLeft.hashCode() + result = 31 * result + topRight.hashCode() + result = 31 * result + bottomRight.hashCode() + result = 31 * result + bottomLeft.hashCode() + return result + } + + companion object { + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): LatLngQuad { + return readFromParcel(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + + private fun readFromParcel(parcel: Parcel): LatLngQuad { + val topLeft = LatLng(parcel) + val topRight = LatLng(parcel) + val bottomRight = LatLng(parcel) + val bottomLeft = LatLng(parcel) + return LatLngQuad(topLeft, topRight, bottomRight, bottomLeft) + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java deleted file mode 100644 index d62794f13..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.NonNull; - -/** - * A geographical span defined by its latitude and longitude span. - */ -public class LatLngSpan implements Parcelable { - - private double mLatitudeSpan; - private double mLongitudeSpan; - - private LatLngSpan(@NonNull Parcel in) { - mLatitudeSpan = in.readDouble(); - mLongitudeSpan = in.readDouble(); - } - - /** - * Creates a LatLgnSpan. - * - * @param latitudeSpan The span used for latitude. - * @param longitudeSpan The span used for longitude. - */ - public LatLngSpan(double latitudeSpan, double longitudeSpan) { - mLatitudeSpan = latitudeSpan; - mLongitudeSpan = longitudeSpan; - } - - /** - * Returns the latitude span. - * - * @return The latitude span. - */ - public double getLatitudeSpan() { - return mLatitudeSpan; - } - - /** - * Sets the latitude span. - * - * @param latitudeSpan The latitude span to set. - */ - public void setLatitudeSpan(double latitudeSpan) { - mLatitudeSpan = latitudeSpan; - } - - /** - * Returns to longitude span. - * - * @return The longitude span. - */ - public double getLongitudeSpan() { - return mLongitudeSpan; - } - - /** - * Sets the longitude span. - * - * @param longitudeSpan The longitude span to set. - */ - public void setLongitudeSpan(double longitudeSpan) { - mLongitudeSpan = longitudeSpan; - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param object The object to compare - * @return True if equal, false if not - */ - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof LatLngSpan) { - LatLngSpan other = (LatLngSpan) object; - return mLongitudeSpan == other.getLongitudeSpan() - && mLatitudeSpan == other.getLatitudeSpan(); - } - return false; - } - - /** - * Inner class responsible for recreating Parcels into objects. - */ - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public LatLngSpan createFromParcel(@NonNull Parcel in) { - return new LatLngSpan(in); - } - - @Override - public LatLngSpan[] newArray(int size) { - return new LatLngSpan[size]; - } - }; - - /** - * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. - * - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out Parcel in which the object should be written - * @param flags Additional flags about how the object should be written - */ - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeDouble(mLatitudeSpan); - out.writeDouble(mLongitudeSpan); - } - - /** - * Returns a hash code value for the object. - * - * @return hash code value of this - */ - @Override - public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(mLatitudeSpan); - result = (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(mLongitudeSpan); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.kt new file mode 100644 index 000000000..0bd0cabae --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.kt @@ -0,0 +1,115 @@ +package com.mapbox.mapboxsdk.geometry + +import android.os.Parcel +import android.os.Parcelable + +/** + * A geographical span defined by its latitude and longitude span. + */ +class LatLngSpan : Parcelable { + /** + * Returns the latitude span. + * + * @return The latitude span. + */ + /** + * Sets the latitude span. + * + * @var latitudeSpan The latitude span to set. + */ + var latitudeSpan: Double + /** + * Returns to longitude span. + * + * @return The longitude span. + */ + /** + * Sets the longitude span. + * + * @var longitudeSpan The longitude span to set. + */ + var longitudeSpan: Double + + private constructor(parcel: Parcel) { + latitudeSpan = parcel.readDouble() + longitudeSpan = parcel.readDouble() + } + + /** + * Creates a LatLgnSpan. + * + * @param latitudeSpan The span used for latitude. + * @param longitudeSpan The span used for longitude. + */ + constructor(latitudeSpan: Double, longitudeSpan: Double) { + this.latitudeSpan = latitudeSpan + this.longitudeSpan = longitudeSpan + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param other The object to compare + * @return True if equal, false if not + */ + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other is LatLngSpan) { + return (longitudeSpan == other.longitudeSpan && latitudeSpan == other.latitudeSpan) + } + return false + } + + /** + * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. + * + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + override fun describeContents(): Int { + return 0 + } + + /** + * Flatten this object in to a Parcel. + * + * @param out Parcel in which the object should be written + * @param flags Additional flags about how the object should be written + */ + override fun writeToParcel(out: Parcel, flags: Int) { + out.writeDouble(latitudeSpan) + out.writeDouble(longitudeSpan) + } + + /** + * Returns a hash code value for the object. + * + * @return hash code value of this + */ + override fun hashCode(): Int { + var result: Int + var temp: Long + temp = java.lang.Double.doubleToLongBits(latitudeSpan) + result = (temp xor (temp ushr 32)).toInt() + temp = java.lang.Double.doubleToLongBits(longitudeSpan) + result = 31 * result + (temp xor (temp ushr 32)).toInt() + return result + } + + companion object { + /** + * Inner class responsible for recreating Parcels into objects. + */ + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): LatLngSpan { + return LatLngSpan(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/PackageInfo.kt similarity index 62% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/package-info.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/PackageInfo.kt index 754af7659..5f1b5dd26 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/package-info.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/PackageInfo.kt @@ -1,4 +1,4 @@ /** * Contains the Mapbox Maps Android Geometry API classes. */ -package com.mapbox.mapboxsdk.geometry; +package com.mapbox.mapboxsdk.geometry diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java deleted file mode 100644 index a304e0962..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -/** - * ProjectedMeters is a projection of longitude, latitude points in Mercator meters. - *

- * these have been projected into Mapbox GL's Mercator projection. Instead of decimal - * degrees, it uses Mercator meters (which are notably not equivalent to SI meters) - * except at the equator. - *

- */ -public class ProjectedMeters implements Parcelable { - - /** - * Inner class responsible for recreating Parcels into objects. - */ - public static final Creator CREATOR = new Creator() { - public ProjectedMeters createFromParcel(@NonNull Parcel in) { - return new ProjectedMeters(in); - } - - public ProjectedMeters[] newArray(int size) { - return new ProjectedMeters[size]; - } - }; - - private double northing; - private double easting; - - /** - * Creates a ProjectedMeters based on projected meters in north and east direction. - * - * @param northing the northing in meters - * @param easting the easting in meters - */ - @Keep - public ProjectedMeters(double northing, double easting) { - this.northing = northing; - this.easting = easting; - } - - /** - * Creates a ProjecteMeters based on another set of projected meters. - * - * @param projectedMeters The projected meters to be based on. - */ - public ProjectedMeters(ProjectedMeters projectedMeters) { - this.northing = projectedMeters.northing; - this.easting = projectedMeters.easting; - } - - /** - * Creates a ProjectedMeters from a Parcel. - * - * @param in The parcel to create from - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - private ProjectedMeters(Parcel in) { - northing = in.readDouble(); - easting = in.readDouble(); - } - - /** - * Get projected meters in north direction. - * - * @return Projected meters in north. - */ - public double getNorthing() { - return northing; - } - - /** - * Get projected meters in east direction. - * - * @return Projected meters in east. - */ - public double getEasting() { - return easting; - } - - /** - * Indicates whether some other object is "equal to" this one. - * - * @param other The object to compare this to - * @return true if equal, false if not - */ - @Override - public boolean equals(@Nullable Object other) { - if (this == other) { - return true; - } - if (other == null || getClass() != other.getClass()) { - return false; - } - - ProjectedMeters projectedMeters = (ProjectedMeters) other; - - return Double.compare(projectedMeters.easting, easting) == 0 - && Double.compare(projectedMeters.northing, northing) == 0; - } - - /** - * Returns a hash code value for the object. - * - * @return the hash code of this - */ - @Override - public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(easting); - result = (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(northing); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - /** - * Returns a string representation of the object. - * - * @return the string representation of this - */ - @NonNull - @Override - public String toString() { - return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]"; - } - - /** - * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. - * - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written - */ - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeDouble(northing); - out.writeDouble(easting); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.kt new file mode 100644 index 000000000..8481e082c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.kt @@ -0,0 +1,142 @@ +package com.mapbox.mapboxsdk.geometry + +import android.os.Parcel +import android.os.Parcelable +import androidx.annotation.Keep + +/** + * ProjectedMeters is a projection of longitude, latitude points in Mercator meters. + * + * + * these have been projected into Mapbox GL's Mercator projection. Instead of decimal + * degrees, it uses Mercator meters (which are notably not equivalent to SI meters) + * except at the equator. + * + */ +class ProjectedMeters : Parcelable { + /** + * Get projected meters in north direction. + * + * @return Projected meters in north. + */ + var northing: Double + private set + + /** + * Get projected meters in east direction. + * + * @return Projected meters in east. + */ + var easting: Double + private set + + /** + * Creates a ProjectedMeters based on projected meters in north and east direction. + * + * @param northing the northing in meters + * @param easting the easting in meters + */ + @Keep + constructor(northing: Double, easting: Double) { + this.northing = northing + this.easting = easting + } + + /** + * Creates a ProjecteMeters based on another set of projected meters. + * + * @param projectedMeters The projected meters to be based on. + */ + constructor(projectedMeters: ProjectedMeters) { + northing = projectedMeters.northing + easting = projectedMeters.easting + } + + /** + * Creates a ProjectedMeters from a Parcel. + * + * @param `in` The parcel to create from + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + private constructor(parcel: Parcel) { + northing = parcel.readDouble() + easting = parcel.readDouble() + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param other The object to compare this to + * @return true if equal, false if not + */ + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other == null || javaClass != other.javaClass) { + return false + } + val projectedMeters = other as ProjectedMeters + return (java.lang.Double.compare(projectedMeters.easting, easting) == 0 && java.lang.Double.compare(projectedMeters.northing, northing) == 0) + } + + /** + * Returns a hash code value for the object. + * + * @return the hash code of this + */ + override fun hashCode(): Int { + var result: Int + var temp: Long + temp = java.lang.Double.doubleToLongBits(easting) + result = (temp xor (temp ushr 32)).toInt() + temp = java.lang.Double.doubleToLongBits(northing) + result = 31 * result + (temp xor (temp ushr 32)).toInt() + return result + } + + /** + * Returns a string representation of the object. + * + * @return the string representation of this + */ + override fun toString(): String { + return "ProjectedMeters [northing=$northing, easting=$easting]" + } + + /** + * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. + * + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + override fun describeContents(): Int { + return 0 + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written + */ + override fun writeToParcel(out: Parcel, flags: Int) { + out.writeDouble(northing) + out.writeDouble(easting) + } + + companion object { + /** + * Inner class responsible for recreating Parcels into objects. + */ + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ProjectedMeters { + return ProjectedMeters(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java deleted file mode 100644 index 79f6a9213..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.NonNull; - -/** - * Contains the four points defining the four-sided polygon that is visible in a map's camera. - * This polygon can be a trapezoid instead of a rectangle, because a camera can have tilt. - * If the camera is directly over the center of the camera, the shape is rectangular, - * but if the camera is tilted, the shape will appear to be a trapezoid whose - * smallest side is closest to the point of view. - */ -public class VisibleRegion implements Parcelable { - - /** - * LatLng object that defines the far left corner of the camera. - */ - public final LatLng farLeft; - - /** - * LatLng object that defines the far right corner of the camera. - */ - public final LatLng farRight; - - /** - * LatLng object that defines the bottom left corner of the camera. - */ - public final LatLng nearLeft; - - /** - * LatLng object that defines the bottom right corner of the camera. - */ - public final LatLng nearRight; - - /** - * The smallest bounding box that includes the visible region defined in this class. - */ - public final LatLngBounds latLngBounds; - - /** - * Creates a VisibleRegion from a Parcel. - * - * @param in The Parcel to create this from - */ - private VisibleRegion(Parcel in) { - this.farLeft = in.readParcelable(LatLng.class.getClassLoader()); - this.farRight = in.readParcelable(LatLng.class.getClassLoader()); - this.nearLeft = in.readParcelable(LatLng.class.getClassLoader()); - this.nearRight = in.readParcelable(LatLng.class.getClassLoader()); - this.latLngBounds = in.readParcelable(LatLngBounds.class.getClassLoader()); - } - - /** - * Creates a VisibleRegion given the four corners of the camera. - * - * @param farLeft A LatLng object containing the latitude and longitude of the far left corner of the region. - * @param farRight A LatLng object containing the latitude and longitude of the far right corner of the region. - * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region. - * @param nearRight A LatLng object containing the latitude and longitude of the near right corner of the region. - * @param latLngBounds The smallest bounding box that includes the visible region defined in this class. - */ - public VisibleRegion(LatLng farLeft, LatLng farRight, LatLng nearLeft, LatLng nearRight, LatLngBounds latLngBounds) { - this.farLeft = farLeft; - this.farRight = farRight; - this.nearLeft = nearLeft; - this.nearRight = nearRight; - this.latLngBounds = latLngBounds; - } - - /** - * Compares this VisibleRegion to another object. - * If the other object is actually a pointer to this object, - * or if all four corners and the bounds of the two objects are the same, - * this method returns true. Otherwise, this method returns false. - * - * @param o The Object to compare with. - * @return true if both objects are the same object. - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof VisibleRegion)) { - return false; - } - if (o == this) { - return true; - } - - VisibleRegion visibleRegion = (VisibleRegion) o; - return farLeft.equals(visibleRegion.farLeft) - && farRight.equals(visibleRegion.farRight) - && nearLeft.equals(visibleRegion.nearLeft) - && nearRight.equals(visibleRegion.nearRight) - && latLngBounds.equals(visibleRegion.latLngBounds); - } - - /** - * The string representation of the object. - * - * @return the string representation of this - */ - @NonNull - @Override - public String toString() { - return "[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight [" - + nearRight + "], latLngBounds [" + latLngBounds + "]]"; - } - - /** - * Returns a hash code value for the object. - * - * @return the hash code - */ - @Override - public int hashCode() { - return ((farLeft.hashCode() + 90) - + ((farRight.hashCode() + 90) * 1000) - + ((nearLeft.hashCode() + 180) * 1000000) - + ((nearRight.hashCode() + 180) * 1000000000)); - } - - /** - * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. - * - * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written - */ - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeParcelable(farLeft, flags); - out.writeParcelable(farRight, flags); - out.writeParcelable(nearLeft, flags); - out.writeParcelable(nearRight, flags); - out.writeParcelable(latLngBounds, flags); - } - - /** - * Inner class responsible for recreating Parcels into objects. - */ - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public VisibleRegion createFromParcel(@NonNull Parcel in) { - return new VisibleRegion(in); - } - - public VisibleRegion[] newArray(int size) { - return new VisibleRegion[size]; - } - }; - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.kt new file mode 100644 index 000000000..df7b3ad18 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.kt @@ -0,0 +1,159 @@ +package com.mapbox.mapboxsdk.geometry + +import android.os.Build +import android.os.Parcel +import android.os.Parcelable + +/** + * Contains the four points defining the four-sided polygon that is visible in a map's camera. + * This polygon can be a trapezoid instead of a rectangle, because a camera can have tilt. + * If the camera is directly over the center of the camera, the shape is rectangular, + * but if the camera is tilted, the shape will appear to be a trapezoid whose + * smallest side is closest to the point of view. + */ +class VisibleRegion : Parcelable { + /** + * LatLng object that defines the far left corner of the camera. + */ + @JvmField + val farLeft: LatLng? + + /** + * LatLng object that defines the far right corner of the camera. + */ + @JvmField + val farRight: LatLng? + + /** + * LatLng object that defines the bottom left corner of the camera. + */ + @JvmField + val nearLeft: LatLng? + + /** + * LatLng object that defines the bottom right corner of the camera. + */ + @JvmField + val nearRight: LatLng? + + /** + * The smallest bounding box that includes the visible region defined in this class. + */ + @JvmField + val latLngBounds: LatLngBounds + + /** + * Creates a VisibleRegion from a Parcel. + * + * @param `in` The Parcel to create this from + */ + @Suppress("DEPRECATION") + private constructor(parcel: Parcel) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + farLeft = parcel.readParcelable(LatLng::class.java.classLoader, LatLng::class.java) + farRight = parcel.readParcelable(LatLng::class.java.classLoader, LatLng::class.java) + nearLeft = parcel.readParcelable(LatLng::class.java.classLoader, LatLng::class.java) + nearRight = parcel.readParcelable(LatLng::class.java.classLoader, LatLng::class.java) + latLngBounds = parcel.readParcelable(LatLngBounds::class.java.classLoader, LatLngBounds::class.java)!! + } else { + farLeft = parcel.readParcelable(LatLng::class.java.classLoader) + farRight = parcel.readParcelable(LatLng::class.java.classLoader) + nearLeft = parcel.readParcelable(LatLng::class.java.classLoader) + nearRight = parcel.readParcelable(LatLng::class.java.classLoader) + latLngBounds = parcel.readParcelable(LatLngBounds::class.java.classLoader)!! + } + } + + /** + * Creates a VisibleRegion given the four corners of the camera. + * + * @param farLeft A LatLng object containing the latitude and longitude of the far left corner of the region. + * @param farRight A LatLng object containing the latitude and longitude of the far right corner of the region. + * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region. + * @param nearRight A LatLng object containing the latitude and longitude of the near right corner of the region. + * @param latLngBounds The smallest bounding box that includes the visible region defined in this class. + */ + constructor(farLeft: LatLng, farRight: LatLng, nearLeft: LatLng, nearRight: LatLng, latLngBounds: LatLngBounds) { + this.farLeft = farLeft + this.farRight = farRight + this.nearLeft = nearLeft + this.nearRight = nearRight + this.latLngBounds = latLngBounds + } + + /** + * Compares this VisibleRegion to another object. + * If the other object is actually a pointer to this object, + * or if all four corners and the bounds of the two objects are the same, + * this method returns true. Otherwise, this method returns false. + * + * @param other The Object to compare with. + * @return true if both objects are the same object. + */ + override fun equals(other: Any?): Boolean { + if (other !is VisibleRegion) { + return false + } + if (other === this) { + return true + } + return farLeft == other.farLeft && farRight == other.farRight && nearLeft == other.nearLeft && nearRight == other.nearRight && latLngBounds == other.latLngBounds + } + + /** + * The string representation of the object. + * + * @return the string representation of this + */ + override fun toString(): String { + return ("[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight [" + nearRight + "], latLngBounds [" + latLngBounds + "]]") + } + + /** + * Returns a hash code value for the object. + * + * @return the hash code + */ + override fun hashCode(): Int { + return farLeft.hashCode() + 90 + (farRight.hashCode() + 90) * 1000 + (nearLeft.hashCode() + 180) * 1000000 + (nearRight.hashCode() + 180) * 1000000000 + } + + /** + * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation. + * + * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance. + */ + override fun describeContents(): Int { + return 0 + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written + */ + override fun writeToParcel(out: Parcel, flags: Int) { + out.writeParcelable(farLeft, flags) + out.writeParcelable(farRight, flags) + out.writeParcelable(nearLeft, flags) + out.writeParcelable(nearRight, flags) + out.writeParcelable(latLngBounds, flags) + } + + companion object { + /** + * Inner class responsible for recreating Parcels into objects. + */ + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): VisibleRegion { + return VisibleRegion(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Extensions.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Extensions.kt new file mode 100644 index 000000000..52143cb71 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Extensions.kt @@ -0,0 +1,7 @@ +package com.mapbox.mapboxsdk.utils + +// Make converting from Java to Kotlin easier +fun Double.Companion.isNaN(d: Double) = d.isNaN() +fun Float.Companion.isNaN(f: Float) = f.isNaN() +fun Double.Companion.isInfinite(d: Double) = d.isInfinite() +fun Float.Companion.isInfinite(f: Double) = f.isInfinite() diff --git a/platform/android/MapboxGLAndroidSDKLint/src/test/java/com/mapbox/mapboxsdk/lint/KeepDetectorTest.kt b/platform/android/MapboxGLAndroidSDKLint/src/test/java/com/mapbox/mapboxsdk/lint/KeepDetectorTest.kt index 452fc1b42..483750a23 100644 --- a/platform/android/MapboxGLAndroidSDKLint/src/test/java/com/mapbox/mapboxsdk/lint/KeepDetectorTest.kt +++ b/platform/android/MapboxGLAndroidSDKLint/src/test/java/com/mapbox/mapboxsdk/lint/KeepDetectorTest.kt @@ -4,14 +4,14 @@ package com.mapbox.mapboxsdk.lint import com.android.tools.lint.checks.infrastructure.TestFiles.java import com.android.tools.lint.checks.infrastructure.TestLintTask.lint import org.junit.Test -*/ + import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner + @Test @RunWith(RobolectricTestRunner::class) class KeepDetectorTest { -/* @Test fun correctClassName() { lint() .allowMissingSdk() @@ -31,5 +31,5 @@ class KeepDetectorTest { .issues(KeepDetector.ISSUE_NOT_KEPT) .run() .expectClean() - }*/ -} + } +} */ diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.kt index e98a59cd4..527df5006 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.kt @@ -79,10 +79,10 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { private fun showMarkers(amount: Int) { var amount = amount - if (mapboxMap == null || locations == null || mapView!!.isDestroyed) { + if (mapboxMap == null || locations == null || mapView.isDestroyed) { return } - mapboxMap!!.clear() + mapboxMap.clear() if (locations!!.size < amount) { amount = locations!!.size } @@ -101,10 +101,10 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { MarkerOptions() .position(latLng) .title(i.toString()) - .snippet(formatter.format(latLng.latitude) + ", " + formatter.format(latLng.longitude)) + .snippet(formatter.format(latLng.latitude) + "`, " + formatter.format(latLng.longitude)) ) } - mapboxMap!!.addMarkers(markerOptionsList) + mapboxMap.addMarkers(markerOptionsList) } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -113,27 +113,27 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { override fun onStart() { super.onStart() - mapView!!.onStart() + mapView.onStart() } override fun onResume() { super.onResume() - mapView!!.onResume() + mapView.onResume() } override fun onPause() { super.onPause() - mapView!!.onPause() + mapView.onPause() } override fun onStop() { super.onStop() - mapView!!.onStop() + mapView.onStop() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - mapView!!.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) } override fun onDestroy() { @@ -141,12 +141,12 @@ class BulkMarkerActivity : AppCompatActivity(), OnItemSelectedListener { if (progressDialog != null) { progressDialog!!.dismiss() } - mapView!!.onDestroy() + mapView.onDestroy() } override fun onLowMemory() { super.onLowMemory() - mapView!!.onLowMemory() + mapView.onLowMemory() } private class LoadLocationTask constructor( diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.kt index dfbc1a84b..aaafaad5f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.kt @@ -235,10 +235,8 @@ class CameraAnimatorActivity : AppCompatActivity(), OnMapReadyCallback { private class LatLngEvaluator : TypeEvaluator { private val latLng = LatLng() override fun evaluate(fraction: Float, startValue: LatLng, endValue: LatLng): LatLng { - latLng.latitude = - (startValue.latitude + (endValue.latitude - startValue.latitude) * fraction) - latLng.longitude = - (startValue.longitude + (endValue.longitude - startValue.longitude) * fraction) + latLng.setLongitude((startValue.latitude + (endValue.latitude - startValue.latitude) * fraction)) + latLng.setLongitude((startValue.longitude + (endValue.longitude - startValue.longitude) * fraction)) return latLng } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt index aceb63083..890e844d0 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt @@ -108,7 +108,7 @@ class LocationFragmentActivity : AppCompatActivity() { component.activateLocationComponent( LocationComponentActivationOptions - .builder(activity!!, style) + .builder(requireActivity(), style) .useDefaultLocationEngine(true) .build() ) @@ -120,7 +120,7 @@ class LocationFragmentActivity : AppCompatActivity() { } override fun onSuccess(result: LocationEngineResult?) { - if (!mapView.isDestroyed) mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0)) + if (!mapView.isDestroyed) mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation!!), 12.0)) } override fun onFailure(exception: Exception) { @@ -173,7 +173,7 @@ class LocationFragmentActivity : AppCompatActivity() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val textView = TextView(inflater.context) - textView.text = "This is an empty Fragment" + textView.text = getString(R.string.this_is_an_empty_fragment) return textView } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedSymbolLayerActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedSymbolLayerActivity.kt index 22ecbe590..3b101f35f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedSymbolLayerActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedSymbolLayerActivity.kt @@ -10,6 +10,7 @@ import android.os.Bundle import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.LinearInterpolator import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.res.ResourcesCompat import com.google.gson.JsonObject import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection @@ -223,7 +224,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { style!!.addSource(randomCarSource!!) style!!.addImage( RANDOM_CAR_IMAGE_ID, - (resources.getDrawable(R.drawable.ic_car_top) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.ic_car_top, null) as BitmapDrawable).bitmap ) val symbolLayer = SymbolLayer(RANDOM_CAR_LAYER, RANDOM_CAR_SOURCE) symbolLayer.withProperties( @@ -249,7 +250,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { ) style!!.addImage( PASSENGER, - (resources.getDrawable(R.drawable.icon_burned) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.icon_burned, null) as BitmapDrawable).bitmap ) val geoJsonSource = GeoJsonSource(PASSENGER_SOURCE, featureCollection) style!!.addSource(geoJsonSource) @@ -277,7 +278,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { taxi = Car(feature, passenger, duration) style!!.addImage( TAXI, - (resources.getDrawable(R.drawable.ic_taxi_top) as BitmapDrawable).bitmap + (ResourcesCompat.getDrawable(resources, R.drawable.ic_taxi_top, null) as BitmapDrawable).bitmap ) taxiSource = GeoJsonSource(TAXI_SOURCE, featureCollection) style!!.addSource(taxiSource!!) @@ -292,7 +293,7 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { } private val latLngInBounds: LatLng - private get() { + get() { val bounds = mapboxMap!!.projection.visibleRegion.latLngBounds val generator = Random() val randomLat = bounds.latSouth + generator.nextDouble() * bounds.latNorth - bounds.latSouth @@ -302,27 +303,27 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { override fun onStart() { super.onStart() - mapView!!.onStart() + mapView.onStart() } override fun onResume() { super.onResume() - mapView!!.onResume() + mapView.onResume() } override fun onPause() { super.onPause() - mapView!!.onPause() + mapView.onPause() } override fun onStop() { super.onStop() - mapView!!.onStop() + mapView.onStop() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - mapView!!.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) } override fun onDestroy() { @@ -333,12 +334,12 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { animator.cancel() } } - mapView!!.onDestroy() + mapView.onDestroy() } override fun onLowMemory() { super.onLowMemory() - mapView!!.onLowMemory() + mapView.onLowMemory() } /** @@ -347,14 +348,8 @@ class AnimatedSymbolLayerActivity : AppCompatActivity() { private class LatLngEvaluator : TypeEvaluator { private val latLng = LatLng() override fun evaluate(fraction: Float, startValue: LatLng, endValue: LatLng): LatLng { - latLng.latitude = ( - startValue.latitude + - (endValue.latitude - startValue.latitude) * fraction - ) - latLng.longitude = ( - startValue.longitude + - (endValue.longitude - startValue.longitude) * fraction - ) + latLng.setLatitude(startValue.latitude + (endValue.latitude - startValue.latitude) * fraction) + latLng.setLongitude(startValue.longitude + (endValue.longitude - startValue.longitude) * fraction) return latLng } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java index a6fdbf558..bfa735883 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java @@ -1,3 +1,5 @@ +package com.mapbox.mapboxsdk.testapp.activity.telemetry; + import android.app.ActivityManager; import android.content.Context; import android.os.Build; @@ -6,6 +8,7 @@ import android.util.DisplayMetrics; import android.view.Display; import android.view.WindowManager; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.gson.Gson; @@ -89,7 +92,7 @@ public class PerformanceMeasurementActivity extends AppCompatActivity { } @Override - protected void onSaveInstanceState(Bundle outState) { + protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } @@ -101,7 +104,7 @@ public class PerformanceMeasurementActivity extends AppCompatActivity { attributes.add( new Attribute<>("test_perf_event", "true")); - List> counters = new ArrayList(); + List> counters = new ArrayList<>(); counters.add(new Attribute<>("elapsed", elapsed)); @@ -146,7 +149,7 @@ public class PerformanceMeasurementActivity extends AppCompatActivity { private static class EventListener extends okhttp3.EventListener { - private Map startTimes = new HashMap<>(); + private final Map startTimes = new HashMap<>(); @Override public void callStart(Call call) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml index 14dfe27eb..6b21dc424 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml @@ -3,4 +3,5 @@ MapLibre Android SDK TestApp fps30 fps60 + This is an empty Fragment