diff --git a/Guibe/Base.lproj/Main.storyboard b/Guibe/Base.lproj/Main.storyboard index 9dbeb8f..76f3797 100644 --- a/Guibe/Base.lproj/Main.storyboard +++ b/Guibe/Base.lproj/Main.storyboard @@ -200,10 +200,15 @@ - + @@ -244,10 +249,12 @@ + + diff --git a/Guibe/MainViewController.swift b/Guibe/MainViewController.swift index 2d80282..7b8c193 100644 --- a/Guibe/MainViewController.swift +++ b/Guibe/MainViewController.swift @@ -7,16 +7,39 @@ // import UIKit +import AVKit +import MapKit +import CoreLocation +import AVFoundation -class MainViewController: UIViewController { +class MainViewController: UIViewController, AVAudioPlayerDelegate { + + let locationManager = CLLocationManager() + var currentCoordinate: CLLocationCoordinate2D! + + var player = AVAudioPlayer() + + var steps = [MKRoute.Step]() + + var stepCounter = 0 + + var previousDistanceToWaypoint: Double = 1000 + var distanceToNextCoord: Double = 1000 + + var startedNavigation: Bool = false + // OUTLETS--------------OUTLETS @IBOutlet weak var menuView: UIView! @IBOutlet weak var menuBtn: UIButton! -// ---------------------------- +// --------------------- + @IBOutlet weak var searchBarBg: UIButton! @IBOutlet weak var searchView: UIView! @IBOutlet weak var searchBar: UISearchBar! @IBOutlet weak var micBtn: UIButton! +// --------------------- + @IBOutlet weak var mapView: MKMapView! + // OUTLETS--------------OUTLETS // ACTIONS--------------ACTIONS @@ -30,10 +53,212 @@ class MainViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + self.searchBarBg.layer.shadowColor = UIColor.black.cgColor + self.searchBarBg.layer.cornerRadius = 10 + self.searchBarBg.layer.shadowOffset = CGSize(width: 5, height: 7) + self.searchBarBg.layer.shadowRadius = 10 + self.searchBarBg.layer.shadowOpacity = 0.2 + + locationManager.delegate = (self as! CLLocationManagerDelegate) + locationManager.desiredAccuracy = kCLLocationAccuracyBest + locationManager.startUpdatingLocation() } //END VIEW DID LOAD - + func getDirections(to destination: MKMapItem) { + let sourcePlacemark = MKPlacemark(coordinate: currentCoordinate) + let sourceMapItem = MKMapItem(placemark: sourcePlacemark) + + let directionsRequest = MKDirections.Request() + directionsRequest.source = sourceMapItem + directionsRequest.destination = destination + directionsRequest.transportType = .walking + + let directions = MKDirections(request: directionsRequest) + directions.calculate { (response, _) in + guard let response = response else { return } + guard let primaryRoute = response.routes.first else { return } + + self.mapView.addOverlay(primaryRoute.polyline) + + self.steps = primaryRoute.steps + for i in 0 ..< primaryRoute.steps.count { + let step = primaryRoute.steps[i] + print(step.instructions) + print(step.distance) + // -----------------------------Geofencing setup + let region = CLCircularRegion(center: step.polyline.coordinate, + radius: 15, + identifier: "\(i)") + // self.locationManager.startMonitoring(for: region) + // -----------------------------Geofencing setup + let circle = MKCircle(center: region.center, radius: region.radius) + self.mapView.addOverlay(circle) + } + + self.startedNavigation = true + self.stepCounter += 1 + } + } } //END OF CLASS + + + +extension ViewController: CLLocationManagerDelegate { + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + guard let currentLocation = locations.first else { return } + currentCoordinate = currentLocation.coordinate + mapView.userTrackingMode = .follow + + if startedNavigation == true { + StepLabel.text = "On step: \(stepCounter)" + let nextStep = steps[stepCounter] + let nextCoord = CLLocation(latitude: nextStep.polyline.coordinate.latitude, longitude: nextStep.polyline.coordinate.longitude) + distanceToNextCoord = currentLocation.distance(from: nextCoord) + devonLbl.text = String(format: "Distance to next waypoint: %.2f meters", distanceToNextCoord) + a.text = String(format: "%.2f", previousDistanceToWaypoint)//"\(previousDistanceToWaypoint)" + b.text = String(format: "%.2f", distanceToNextCoord)//"\(distanceToNextCoord)" + + if distanceToNextCoord < previousDistanceToWaypoint { + previousDistanceToWaypoint = currentLocation.distance(from: nextCoord) + } + if distanceToNextCoord > previousDistanceToWaypoint + 10 { + devonLbl.text = String(format: "WRONG WAY (%.2f > %.2f)", distanceToNextCoord, previousDistanceToWaypoint+10) + previousDistanceToWaypoint = distanceToNextCoord - 5 + playTurnArd() + } + if distanceToNextCoord < 15 { + stepCounter += 1 + if stepCounter < steps.count { + // let currentStep = steps[stepCounter] + let message = "\(steps[stepCounter-1].instructions)" + directionsLabel.text = message + let maneuverCommand = String(message.prefix(10)) + switch (maneuverCommand) { + case "Turn right": + playRight() + break; + case "Bear right": + playRight() + break; + case "Turn left ": + playLeft() + break; + case "Bear left": + playLeft() + break; + case "The destin": + playDone() + + default: + playErr() + currentStepLbl.text = "ERR: \(message)" + break; + } + + // let speechUtterance = AVSpeechUtterance(string: message) + // speechSynthesizer.speak(speechUtterance) + previousDistanceToWaypoint = 1000 + } else { + let message = "Arrived at destination" + directionsLabel.text = message + // let speechUtterance = AVSpeechUtterance(string: message) + // speechSynthesizer.speak(speechUtterance) + stepCounter = 0 + previousDistanceToWaypoint = 1000 + cancelView.isHidden = true + searchBar.isHidden = false + // locationManager.monitoredRegions.forEach({ self.locationManager.stopMonitoring(for: $0) }) + + } + } + } + + } + + func playRight(){ +// currentStepLbl.text = "COM: RIGHT" + let path = Bundle.main.path(forResource: "xright", ofType : "mp3")! + let url = URL(fileURLWithPath : path) + do { + player = try AVAudioPlayer(contentsOf: url) + player.delegate = self + player.play() + } catch {} + } + + func playLeft(){ +// currentStepLbl.text = "COM: LEFT" + let path = Bundle.main.path(forResource: "xleft", ofType : "mp3")! + let url = URL(fileURLWithPath : path) + do { + player = try AVAudioPlayer(contentsOf: url) + player.delegate = self + player.play() + } catch {} + } + + func playErr(){ + // currentStepLbl.text = "COM: ERROR!!!" + return + } + + func playTurnArd(){ +// currentStepLbl.text = "COM: UTURN" + let path = Bundle.main.path(forResource: "xboth", ofType : "mp3")! + let url = URL(fileURLWithPath : path) + do { + player = try AVAudioPlayer(contentsOf: url) + player.delegate = self + player.play() + } catch {} + } + + func playDone(){ +// currentStepLbl.text = "COM: DONE" + } +} + + + + +extension ViewController: UISearchBarDelegate { + func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { + searchBar.endEditing(true) //HIDES LE KEYBOARD + + let localSearchRequest = MKLocalSearch.Request() + localSearchRequest.naturalLanguageQuery = searchBar.text + let region = MKCoordinateRegion(center: currentCoordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)) + localSearchRequest.region = region + let localSearch = MKLocalSearch(request: localSearchRequest) + localSearch.start { (response, _) in + guard let response = response else { return } + guard let firstMapItem = response.mapItems.first else { return } + self.getDirections(to: firstMapItem) + } + + } +} + + +extension ViewController: MKMapViewDelegate { + func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { + if overlay is MKPolyline { + let renderer = MKPolylineRenderer(overlay: overlay) + renderer.strokeColor = .blue + renderer.alpha = 0.7 + renderer.lineWidth = 10 + return renderer + } + if overlay is MKCircle { + let renderer = MKCircleRenderer(overlay: overlay) + renderer.strokeColor = .red + renderer.fillColor = .red + renderer.alpha = 0.4 + return renderer + } + return MKOverlayRenderer() + } +}