diff --git a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java index 9d40520..c223575 100644 --- a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java +++ b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java @@ -1,111 +1,111 @@ /* BusTO - Data components Copyright (C) 2021 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.data; import android.content.Context; import android.content.SharedPreferences; import androidx.annotation.NonNull; import it.reyboz.bustorino.R; import static android.content.Context.MODE_PRIVATE; import androidx.preference.PreferenceManager; import it.reyboz.bustorino.fragments.SettingsFragment; import it.reyboz.bustorino.map.MapLibreUtils; import java.util.HashSet; import java.util.Set; /** * Static class for commonly used SharedPreference operations */ public abstract class PreferencesHolder { public static final String PREF_GTFS_DB_VERSION = "gtfs_db_version"; public static final String PREF_INTRO_ACTIVITY_RUN ="pref_intro_activity_run"; public static final String DB_GTT_VERSION_KEY = "NextGenDB.GTTVersion"; public static final String DB_LAST_UPDATE_KEY = "NextGenDB.LastDBUpdate"; public static final String PREF_FAVORITE_LINES = "pref_favorite_lines"; public static final Set KEYS_MERGE_SET = Set.of(PREF_FAVORITE_LINES); public static final Set IGNORE_KEYS_LOAD_MAIN = Set.of(PREF_GTFS_DB_VERSION, PREF_INTRO_ACTIVITY_RUN, DB_GTT_VERSION_KEY, DB_LAST_UPDATE_KEY); public static SharedPreferences getMainSharedPreferences(Context context){ return context.getSharedPreferences(context.getString(R.string.mainSharedPreferences), MODE_PRIVATE); } public static SharedPreferences getAppPreferences(Context con){ return PreferenceManager.getDefaultSharedPreferences(con); } public static int getGtfsDBVersion(SharedPreferences pref){ return pref.getInt(PREF_GTFS_DB_VERSION,-1); } public static void setGtfsDBVersion(SharedPreferences pref,int version){ SharedPreferences.Editor ed = pref.edit(); ed.putInt(PREF_GTFS_DB_VERSION,version); ed.apply(); } /** * Check if the introduction activity has been run at least one * @param con the context needed * @return true if it has been run */ public static boolean hasIntroFinishedOneShot(Context con){ final SharedPreferences pref = getMainSharedPreferences(con); return pref.getBoolean(PREF_INTRO_ACTIVITY_RUN, false); } public static boolean addOrRemoveLineToFavorites(Context con, String gtfsLineId, boolean addToFavorites){ final SharedPreferences pref = getMainSharedPreferences(con); final HashSet favorites = new HashSet<>(pref.getStringSet(PREF_FAVORITE_LINES, new HashSet<>())); boolean modified = true; if(addToFavorites) favorites.add(gtfsLineId); else if(favorites.contains(gtfsLineId)) favorites.remove(gtfsLineId); else modified = false; // we are not changing anything if(modified) { final SharedPreferences.Editor editor = pref.edit(); editor.putStringSet(PREF_FAVORITE_LINES, favorites); editor.apply(); } return modified; } public static HashSet getFavoritesLinesGtfsIDs(@NonNull Context con){ final SharedPreferences pref = getMainSharedPreferences(con); return new HashSet<>(pref.getStringSet(PREF_FAVORITE_LINES, new HashSet<>())); } public static String getMapLibreStyleFile(Context con){ final SharedPreferences pref = getAppPreferences(con); /*final String mapStyle_val = pref.getString(SettingsFragment.LIBREMAP_STYLE_PREF_KEY, ""); return switch (mapStyle_val) { //MUST MATCH IN keys.xml -> map_style_pref_values case "versatiles_c" -> MapLibreUtils.STYLE_VERSATILES_COLORFUL_JSON; case "bright" -> MapLibreUtils.STYLE_BRIGHT_DEFAULT_JSON; //default is "bright" default -> MapLibreUtils.STYLE_VERSATILES_COLORFUL_JSON; }; */ - return MapLibreUtils.STYLE_VERSATILES_COLORFUL_JSON; + return MapLibreUtils.getDefaultStyleJson(); } } diff --git a/app/src/main/java/it/reyboz/bustorino/map/MapLibreUtils.kt b/app/src/main/java/it/reyboz/bustorino/map/MapLibreUtils.kt index 8be62a1..0430d26 100644 --- a/app/src/main/java/it/reyboz/bustorino/map/MapLibreUtils.kt +++ b/app/src/main/java/it/reyboz/bustorino/map/MapLibreUtils.kt @@ -1,225 +1,228 @@ package it.reyboz.bustorino.map import android.animation.TypeEvaluator import android.content.Context import android.util.Log import it.reyboz.bustorino.backend.Stop import org.maplibre.android.geometry.LatLng import org.maplibre.android.location.LocationComponentActivationOptions import org.maplibre.android.location.LocationComponentOptions import org.maplibre.android.location.engine.LocationEngineRequest import org.maplibre.android.maps.Style import org.maplibre.geojson.Point import org.maplibre.turf.TurfMeasurement class MapLibreUtils { companion object{ const val STYLE_BRIGHT_DEFAULT_JSON = "map_style_good_noshops.json" const val STYLE_VERSATILES_COLORFUL_JSON = "versatiles_colorful_light.json" private const val DEBUG_TAG ="BusTO-MapLibreUtils" + @JvmStatic + fun getDefaultStyleJson() = STYLE_VERSATILES_COLORFUL_JSON + @JvmStatic fun shortestRotation(from: Float, to: Float): Float { var delta = (to - from) % 360 if (delta > 180) delta -= 360 if (delta < -180) delta += 360 return from + delta } @JvmStatic fun buildLocationComponentActivationOptions( style: Style, locationComponentOptions: LocationComponentOptions, context: Context ): LocationComponentActivationOptions { return LocationComponentActivationOptions .builder(context, style) .locationComponentOptions(locationComponentOptions) .useDefaultLocationEngine(true) .locationEngineRequest( LocationEngineRequest.Builder(750) .setFastestInterval(750) .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY) .build() ) .build() } @JvmStatic fun calcDistanceInSegment(points: List, from: Int, to:Int): Double{ var d=0.0 var prev = points[from] for(i in from+1..to){ d += prev.distanceTo(points[i]) prev = points[i] } return d } @JvmStatic fun findIndexMidPoint(points: List, from: Int, to: Int, distThresh:Double): Int{ var totdist=0.0 var idx = -2 var prev = points[from] for(i in from+1..to){ totdist += prev.distanceTo(points[i]) prev = points[i] if (totdist >= distThresh){ idx = i break } } if(idx==-2) throw Error("Distance out of bounds, total distance is $totdist") return idx } @JvmStatic fun findPointsToPutDirectionMarkers(polyPoints: List, stops: List, distanceIcon: Double): List{ val closestIndices = findIndicesClosestPointsForStops(polyPoints, stops) Log.d(DEBUG_TAG, "idcs: $closestIndices") val distancesSec = mutableListOf() var pi = closestIndices[0] val cumulativeDist = mutableListOf() var sum = 0.0 val pointsOutput = mutableListOf() var nPoints = 0 var distFromLastPoint = 0.0 for(i in 1..= distanceIcon){ Log.d(DEBUG_TAG, "Add between stop ${stops[i-1]} and stop ${stops[i]}, distance between: $dd") if(dd>100) { val imid = findIndexMidPoint(polyPoints, pi, newi, dd / 2) pointsOutput.add(imid) nPoints += 1 distFromLastPoint=0.0 } } else{ //add the last distance //distFromLastPoint+=dd/2 } pi= newi } return pointsOutput } /* VERSION WITH TOTAL DISTANCE val distancesSec = mutableListOf() var prevk = 0 val cumulativeDist = mutableListOf() var sum = 0.0 val pointsOutput = mutableListOf() var nPoints = 0 //for(i in 1..= distanceIcon ){ //Log.d(DEBUG_TAG, "Add between stop ${stops[lastStopidx]} and stop ${stops[lastStopidx+1]}") //find closest stops var stopDist = Math.min(polyPoints[prevk].distanceTo(polyPoints[lastStopidx]),polyPoints[k].distanceTo(polyPoints[lastStopidx])) if(lastStopidx+1 < stops.size){ stopDist = Math.min(stopDist, Math.min(polyPoints[prevk].distanceTo(polyPoints[lastStopidx+1]),polyPoints[k].distanceTo(polyPoints[lastStopidx+1])) ) } if(stopDist>100) { val imid = findIndexMidPoint(polyPoints, prevk, k, dd / 2) pointsOutput.add(imid) nPoints += 1 distFromLast = 0.0 } } prevk = k if (k>closestIndices[lastStopidx]) lastStopidx +=1 } return pointsOutput */ @JvmStatic fun splitPolyWhenDistanceTooBig(points: List, distMax: Double): List{ val outList = mutableListOf(points[0]) var oldP = points[0] for(i in 1.. distMax){ val newLat = (oldP.latitude+newP.latitude)/2 val newLong = (oldP.longitude+newP.longitude)/2 val extraP = LatLng(newLat,newLong) outList.add(extraP) } outList.add(newP) oldP=newP } return outList } @JvmStatic fun findIndicesClosestPointsForStops(points:List, stops:List): List { val closestIndices = stops.map { s-> val p = LatLng(s.latitude!!, s.longitude!!) var dist = 10_000_000.0 // in meters var id = -1 for (j in points.indices){ val newd = p.distanceTo(points[j]) if (newd { 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 return latLng } } } \ No newline at end of file