Restrict GMSMapView to certain bounds - ios

I have two coordinates, and I need to restrict my Google Maps map to the frame bounded by those two coordinates. For example, I have
let bounds = GMSCoordinateBounds(
coordinate: CLLocationCoordinate2D(
latitude: 59.615440364671244,
longitude: -17.978949286043644
), coordinate: CLLocationCoordinate2D(
latitude: 33.963318167747758,
longitude: 21.442294009029865
)
)
Then, I write,
map.cameraTargetBounds = bounds
However, this does nothing to restrict the bounds of the map while it should. According to the documentation,
If not nil, [cameraTargetBounds] constrains the camera target so that gestures cannot cause it to leave the specified bounds.
This question did not help me, partially because I must allow zooming as well as panning––it just must be restricted to a certain area.
Why is this not working, and how can I fix it?

You have to use GoogleFletcher. In this we will implement two filters (GMSCoordinateBound and Type). In start bound cordinate we will put current location and at end bound we will just add 1 in our current location cordinates.
Hopefully it helps.
let location = locations.last!
let neBoundsCorner = CLLocationCoordinate2D(latitude:location.coordinate.latitude,
longitude: location.coordinate.longitude)
let swBoundsCorner = CLLocationCoordinate2D(latitude: location.coordinate.latitude + 1, longitude: location.coordinate.longitude + 1)
let bounds = GMSCoordinateBounds(coordinate: neBoundsCorner,coordinate: swBoundsCorner)
let filter = GMSAutocompleteFilter()
filter.type = .establishment
fetcher = GMSAutocompleteFetcher(bounds: bounds, filter: filter)

Related

Google Place auto complete API bounds not working in swift iOS

I have implemented google place autocomplete api and I have applied bounds to restrict my auto complete search to one specific city Orlando, FL, USA but Google place api is not filtering data for only this city. It is searching placing all over USA and other cities name outside USA. I want google autocomplete api to return only this city addresses. Here is the code for same:
let placesClient = GMSPlacesClient()
let searchBound = getCoordinateBounds(latitude: CLLocationDegrees(28.5383), longitude: CLLocationDegrees(81.3792), distance: 1.45)
let filter = GMSAutocompleteFilter()
filter.country = "USA"
placesClient.autocompleteQuery(text!, bounds: searchBound, filter: filter, callback: { (results, error) in
})
//My getCoordinateBounds method
func getCoordinateBounds(latitude:CLLocationDegrees ,
longitude:CLLocationDegrees,
distance:Double = 0.001)->GMSCoordinateBounds{
let center = CLLocationCoordinate2D(latitude: latitude,
longitude: longitude)
let northEast = CLLocationCoordinate2D(latitude: center.latitude + distance, longitude: center.longitude + distance)
let southWest = CLLocationCoordinate2D(latitude: center.latitude - distance, longitude: center.longitude - distance)
return GMSCoordinateBounds(coordinate: northEast,
coordinate: southWest)
}
Note: I want to filter addresses those are around 100 miles radius of this latitude and longitude (that why I have given degree to 1.45). Another thing I added country filer USA after I found that my bounds filter is not working properly. So far I am able to restrict address search to USA.
You should also define the boundsMode parameter in your placesClient.autocompleteQuery() call. Have a look at the documentation:
https://developers.google.com/places/ios-api/reference/interface_g_m_s_places_client
boundsMode must be equal to GMSAutocompleteBoundsMode.Restrict to
interpret bounds as a restrict. By default bounds are interpreted as bias that's why you are getting results from outside.
https://developers.google.com/places/ios-api/reference/group___autocomplete_bounds_mode#gafbfae308afa98048c1e97864baa88568
let placesClient = GMSPlacesClient()
let searchBound = getCoordinateBounds(latitude: CLLocationDegrees(28.5383), longitude: CLLocationDegrees(81.3792), distance: 1.45)
let filter = GMSAutocompleteFilter()
filter.country = "USA"
placesClient.autocompleteQuery(text!, bounds: searchBound, boundsMode: GMSAutocompleteBoundsMode.Restrict, filter: filter, callback: { (results, error) in
})
The parameter boundsMode was introduced in SDK 2.5
I hope this helps!

Set location on Google map on iOS

I'm basically implementing a functionality where after a user moves the map a button appears, and when the button is selected a new search happens in visible area. The problem is the visible area is not accurate, so when I try to zoom into it again it zooms out.
every time I click the button the function below is called and the map zooms out. I understand that not calling animate and removing the code will avoid the zoom, but I want to know why the zoom is happening, because this may cause problems elsewhere
#IBAction func updateSearchSelected(sender: UIButton) {
let northEast = CLLocationCoordinate2D(latitude: mapView!.projection.visibleRegion().farRight.latitude, longitude: mapView!.projection.visibleRegion().farRight.longitude)
let southWest = CLLocationCoordinate2D(latitude: mapView!.projection.visibleRegion().nearLeft.latitude, longitude: mapView!.projection.visibleRegion().nearLeft.longitude)
print("northEast \(northEast)")
print("southWest \(southWest)")
let coordinateBounds = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest)
let cameraUpdate = GMSCameraUpdate.fit(coordinateBounds)
mapView?.animate(with: cameraUpdate)
}
Here are the logs after clicking the button 3 times
northEast CLLocationCoordinate2D(latitude: 37.84227633765466, longitude: -122.38477706909181)
southWest CLLocationCoordinate2D(latitude: 37.674750313908689, longitude: -122.50391006469727)
northEast CLLocationCoordinate2D(latitude: 37.859492217765393, longitude: -122.37251903861761)
southWest CLLocationCoordinate2D(latitude: 37.657491381296779, longitude: -122.51616809517145)
northEast CLLocationCoordinate2D(latitude: 37.880245733530728, longitude: -122.35773839056492)
southWest CLLocationCoordinate2D(latitude: 37.636675535472314, longitude: -122.53094874322414)
You have to set the zoom level to what you want it to be when you call GMSCameraPosition.camera , for example:
let camera = GMSCameraPosition.camera(withLatitude: -33.8683,
longitude: 151.2086,
zoom: 16)
See: https://developers.google.com/maps/documentation/ios-sdk/views#using_gmscameraupdate
See the section titled Camera Position:
"The map view is modeled as a camera looking down on a flat plane. The position of the camera (and hence the rendering of the map) is specified by the following properties: latitude/longitude location, zoom, bearing and viewing angle."

Remaining distance and path on GMSPath from current Location

I am trying to update remaning distance and duration while traveling by using Google map API. I have a whole path, duration and distance but when he cover the distance, how can I get the the remaining distance and duration? I have tried GMSGeometryDistance but it's not giving me the correct distance. and I also don't want to call API again, but methods like GMSGeometryDistance.
let to = CLLocationCoordinate2D(latitude: 24.948021, longitude: 67.091186)
let from = CLLocationCoordinate2D(latitude: 24.891592, longitude: 67.084320)
let camera = GMSCameraPosition.cameraWithTarget(to, zoom: 12)
let mapView = GMSMapView.mapWithFrame(CGRectZero, camera:camera)
GoogleMapsServices.drawPath(mapView, fromPoint:from, toPoint: to, completionHandler: {(json: JSON, path: GMSPath) -> () in
if GMSGeometryIsLocationOnPathTolerance(to, path, true, 5) {
print(GMSGeometryDistance(from, to))
}
})
self.view = mapView

how can I fetch the longitude and latitude from a specific point on my mapview in swift?

I have a MKMapView in my app and currently I'm fetching the center point of this map by using:
longitude = mapView.centerCoordinate.longitude
latitude = mapView.centerCoordinate.latitude
but now instead of taking the center point of the map I want to take a specific point that is 100px below the top edge of my mapview. So normally I would use something like:
longitude = mapView.centerCoordinate.longitude
latitude = mapView.(centerCoordinate+100px).latitude
But that's not how that works apparently. Is there any way of fetching a specific point from mkmapview?
Try this:
let frame = mapView.frame
let myPoint = CGPointMake(frame.midX, 100)
let myCoordinate = mapView.convertPoint(myPoint, toCoordinateFromView: mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = myCoordinate
annotation.title = "My Point"
mapView.addAnnotation(annotation)
Used the the MapKit method:
convertPoint:toCoordinateFromView:

Fit entire Google Map in zoom level in Swift project

I have a google map with a bunch of coordinates
path.addCoordinate(CLLocationCoordinate2DMake(-37.813047, 144.959911))
path.addCoordinate(CLLocationCoordinate2DMake(-37.814895, 144.960759))
path.addCoordinate(CLLocationCoordinate2DMake(-37.814361, 144.963140))
path.addCoordinate(CLLocationCoordinate2DMake(-37.812386, 144.962239))
I would like the map to be automatically zoomed to the best level based on the points however I can't find anything relating to this.
I have this working:
var vancouver = CLLocationCoordinate2DMake(-37.813047, 144.959911)
var calgary = CLLocationCoordinate2DMake(-37.814361, 144.963140)
var bounds = GMSCoordinateBounds(coordinate: vancouver, coordinate: calgary)
var camera = viewMap.cameraForBounds(bounds, insets:UIEdgeInsetsZero)
viewMap.camera = camera
however it only accepts 2 coordinates where I may have up to 100
Thanks
You can use GMSCoordinateBounds(path:) to fit all coordinates. But it will display a world size scale if you update the camera right after your another update. So you can use dispatch_after to solve the problem.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor();
let camera = GMSCameraPosition.cameraWithLatitude(-37.813047, longitude: -72.8561644, zoom:5)
mapView = GMSMapView.mapWithFrame(CGRectZero, camera:camera)
let marker = GMSMarker()
marker.position = camera.target
marker.snippet = "Hello World"
marker.appearAnimation = kGMSMarkerAnimationPop
marker.map = mapView
self.view = mapView
delay(seconds: 2) { () -> () in
let path = GMSMutablePath()
path.addCoordinate(CLLocationCoordinate2DMake(37.36, -122.0))
path.addCoordinate(CLLocationCoordinate2DMake(37.45, -122.0))
path.addCoordinate(CLLocationCoordinate2DMake(37.45, -122.2))
path.addCoordinate(CLLocationCoordinate2DMake(37.36, -122.2))
path.addCoordinate(CLLocationCoordinate2DMake(37.36, -122.0))
let rectangle = GMSPolyline(path: path)
rectangle.map = self.mapView
let bounds = GMSCoordinateBounds(path: path)
self.mapView!.animateWithCameraUpdate(GMSCameraUpdate.fitBounds(bounds, withPadding: 15.0))
}
}
The delay method uses the dispatch_after:
func delay(#seconds: Double, completion:()->()) {
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64( Double(NSEC_PER_SEC) * seconds ))
dispatch_after(popTime, dispatch_get_main_queue()) {
completion()
}
}
Iterate through your points. The southwest corner is the minimum latitude and longitude. The northeast corner is the maximum latitude and longitude. Once you have those two points, pass them into your cameraForBounds method.
Try finding an optimal viewing box on google maps by:
-Clicking on the north east corner of the area you think will cover the coordinates in a browser. Note the lat & long.
-Then click the south east corner in the same area which you think will enclose all the coordinates & note the lat & long.
Put the latitudes & longitudes in the respective variables of the below code:
var southWest = CLLocationCoordinate2DMake(latitide,longititude)
var northEast = CLLocationCoordinate2DMake(latitude,longitude)
var bounds = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest)
var camera = mapView.cameraForBounds(bounds, insets:UIEdgeInsetsZero)
mapView.camera = camera;

Resources