Untitled
unknown
plain_text
8 months ago
11 kB
0
Indexable
Never
package com.example.projektmunka.fragment import android.location.Location import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.RadioButton import android.widget.RadioGroup import androidx.fragment.app.Fragment import com.example.projektmunka.RouteOptimizers.CircularDifficultRouteGenerator import com.example.projektmunka.RouteUtils.calculateGeodesicDistance import com.example.projektmunka.RouteUtils.calculateSearchArea import com.example.projektmunka.RouteUtils.displayCircularRoute import com.example.projektmunka.RouteUtils.fetchCityGraph import com.example.projektmunka.RouteUtils.fetchNodes import com.example.projektmunka.RouteUtils.findNearestOSMNode import com.example.projektmunka.RouteUtils.getElevationData import com.example.projektmunka.data.ImportanceEvaluator import com.example.projektmunka.data.Node import com.example.projektmunka.data.User import com.example.projektmunka.databinding.FragmentForm2Binding import com.example.projektmunka.utils.NominatimReverseGeocoding import com.google.android.material.textfield.TextInputEditText import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.jgrapht.Graph import org.jgrapht.graph.DefaultWeightedEdge import org.osmdroid.views.MapView import java.util.concurrent.CountDownLatch class Form1Fragment(osmMap: MapView, user: User, currentLocation: Location) : Fragment() { private val osmMap: MapView = osmMap private val user: User = user private val currentLocation: Location = currentLocation private lateinit var binding: FragmentForm2Binding lateinit var editTextAddress: TextInputEditText lateinit var radioGroupLocation: RadioGroup lateinit var editTextTargetLocation: TextInputEditText private var poiToClosestNonIsolatedNode: MutableMap<Node, Node> = mutableMapOf() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentForm2Binding.inflate(inflater, container, false) val rootView = binding.root editTextAddress = binding.editTextAddress radioGroupLocation = binding.radioGroupLocation editTextTargetLocation = binding.editTextTargetLocation val btnSetActualAddress = binding.btnSetActualAddress val btnCreateRoute = binding.btnCreateRoute btnSetActualAddress.setOnClickListener { // Handle the "Set my actual address" button click here // You might want to implement a separate logic for this button //setActualLocationMethod() } btnCreateRoute.setOnClickListener { println("0") run() } return rootView } private fun performReverseGeocoding( address: String, callback: (Double, Double) -> Unit, errorCallback: () -> Unit ) { val reverseGeocodingTask = NominatimReverseGeocoding { result -> if (result != null) { val latitude = result.first val longitude = result.second Log.d("YourActivity", "Latitude: $latitude, Longitude: $longitude") callback(latitude, longitude) } else { Log.e("YourActivity", "No location found.") errorCallback() } } reverseGeocodingTask.execute(address) } private fun performReverseGeocodingBlocking(address: String): Pair<Double, Double>? { // Use CountDownLatch to wait for the result val latch = CountDownLatch(1) var result: Pair<Double, Double>? = null val reverseGeocodingTask = NominatimReverseGeocoding { taskResult -> result = if (taskResult != null) { Pair(taskResult.first, taskResult.second) } else { null } latch.countDown() // Release the latch to signal completion } // Execute the reverse geocoding task reverseGeocodingTask.execute(address) // Suspend the coroutine until the result is available latch.await() return result } private fun test() { runBlocking { val selectedRadioButtonId = radioGroupLocation.checkedRadioButtonId val selectedRadioButton = binding.root.findViewById<RadioButton>(selectedRadioButtonId) val sourceAddress = editTextAddress.text.toString() if (selectedRadioButton != null) { var source = Pair(0.0, 0.0) val selectedOptionText = selectedRadioButton.text.toString() if (selectedOptionText == "Choose Address") { source = async { performReverseGeocodingBlocking(sourceAddress) }.await()!! } else if (selectedOptionText == "Set Actual Location") { source = Pair(currentLocation.latitude, currentLocation.longitude) } } } } private fun run() { val maxWalkingTimeInHours = 1.5 // órában megadva val desiredRouteLength = maxWalkingTimeInHours * 4 // 1. In fitness function we use distance measure in meters. Ld is the desired distance // caclulated as desired route time (provided by user, and this is M) multiplied by // average walking speed of 4 km per hour. val rOpt = calculateROpt(1.1, maxWalkingTimeInHours) val searchArea = calculateSearchArea(rOpt) println("1") GlobalScope.launch(Dispatchers.IO) { // Use the findNearestOSMNode function to get the nearest node val nearestNode = findNearestOSMNode(currentLocation, 300.0) ?: return@launch println("2") val nodes = fetchNodes(nearestNode.lat, nearestNode.lon, 600.0) ?: return@launch val evaluatedNodes = nodes.let { evaluateNodes(it) } val importantPOIs = evaluatedNodes.let { selectImportantPOIs(it, 0.1) } println("3") val cityGraph = fetchCityGraph(nearestNode.lat, nearestNode.lon, 600.0) ?: return@launch println("4") runBlocking { async { getElevationData(cityGraph) } }.await() println("5") val nearestNodeNonIsolated = findClosestNonIsolatedNode(cityGraph, nearestNode, 0.0)!! for (poi in importantPOIs) { val closestNonIsolatedNode = findClosestNonIsolatedNode(cityGraph, poi, 0.0) poiToClosestNonIsolatedNode[poi] = closestNonIsolatedNode!! } println("5") val generator = CircularDifficultRouteGenerator( cityGraph, poiToClosestNonIsolatedNode, importantPOIs, 5, desiredRouteLength, 10.0, searchArea, 20, 5, 50 ) val bestRoute = generator.runGeneticAlgorithm(nearestNodeNonIsolated) val connectedRoute = generator.connectPois(nearestNodeNonIsolated, bestRoute, cityGraph) displayCircularRoute(osmMap, bestRoute, connectedRoute, nearestNodeNonIsolated) // val milestones = addMilestones(connectedRoute, 0.9, cityGraph) //addMarkers(osmMap, milestones) } } fun calculateROpt(pedestrianSpeed: Double, maxWalkingTimeInHours: Double): Double { val maxWalkingTimeInSeconds = maxWalkingTimeInHours * 3600 val rMax = (pedestrianSpeed * maxWalkingTimeInSeconds) / 2 return (1.0 / 3.0) * 2 * rMax } fun evaluateNodes(nodes: List<Node>): List<Node> { val evaluatedNodes = nodes.map { node -> val importance = ImportanceEvaluator.evaluate(node) node.copy(importance = importance) } // Filter nodes with importance greater than 0 return evaluatedNodes.filter { it.importance > 0 } } fun selectImportantPOIs(pois: List<Node>, maxDistance: Double): List<Node> { // Filter POIs by importance (> 2) val filteredPOIs = pois.filter { it.importance > 2 } // Group POIs by distance val groupedPOIs = mutableListOf<List<Node>>() // Create a copy of filtered POIs to work with val remainingPOIs = filteredPOIs.toMutableList() while (remainingPOIs.isNotEmpty()) { val currentGroup = mutableListOf<Node>() val seedPOI = remainingPOIs.removeAt(0) // Select the first POI as the seed currentGroup.add(seedPOI) val iterator = remainingPOIs.iterator() while (iterator.hasNext()) { val poi = iterator.next() val distance = calculateGeodesicDistance(seedPOI, poi) if (distance <= maxDistance) { // Add the POI to the current group currentGroup.add(poi) iterator.remove() } } // Add the current group to the list of grouped POIs groupedPOIs.add(currentGroup) } // Select the most important POI from each group val selectedPOIs = groupedPOIs.map { group -> group.maxByOrNull { it.importance }!! } return selectedPOIs } fun findClosestNonIsolatedNode( graph: Graph<Node, DefaultWeightedEdge>, isolatedNode: Node, exitDistance: Double ): Node? { // If the provided node is not isolated, return it if (graph.degreeOf(isolatedNode) > 0) { return isolatedNode } // Use BFS to find non-isolated nodes and their distances var closestNode: Node? = null var minDistance = Double.POSITIVE_INFINITY for (current in graph.vertexSet()) { if (graph.degreeOf(current) > 0) { val distance = calculateGeodesicDistance(isolatedNode, current) if (distance < minDistance) { minDistance = distance closestNode = current if (minDistance <= exitDistance) { return closestNode } } } } return closestNode } }
Leave a Comment