Get viewport coordinates from mapView? regionDidChanged swift - swift

The following function is called when the user moved the map.
It is possible to get the viewport? Viewport is latitude and longitude of north/east and the lat. and lon. of south/west.
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool){
print("The \(mapView.centerCoordinate)")
print("the maprect \(mapView.visibleMapRect.origin)")
print("the maprect \(mapView.visibleMapRect.size)")
//I find just this attributes for mapView
}
I don't know how get the viewports out of my data. I can't find anything in the www.
The destination is that I log the coordinates with google analytics and another tool evaluate the datas.
Has somebody an idea? Thanks a lot

MapKit
let northEast = mapView.convertPoint(CGPoint(x: mapView.bounds.width, y: 0), toCoordinateFromView: mapView)
let southWest = mapView.convertPoint(CGPoint(x: 0, y: mapView.bounds.height), toCoordinateFromView: mapView)
googleMaps
mapView has a property "projection" where you can use "coordinateForPoint" to convert a point from the mapView to a coordinate. so the following could work:
swift 3 for google maps
let northEast = mapView.projection.coordinate(for: CGPoint(x: mapView.layer.frame.width, y: 0))
let southWest = mapView.projection.coordinate(for: CGPoint(x: 0, y: mapView.layer.frame.height))
swift 2
let northEast = mapView.projection.coordinateForPoint(CGPoint(x: mapWidth, y: 0 ))
let southWest = mapView.projection.coordinateForPoint(CGPoint(x: 0, y: mapHeight))
you just need to enter your mapView width and height

Based on fel1xw answer
Swift 3 MapKit
let northEast = mapView.convert(CGPoint(x: mapView.bounds.width, y: 0), toCoordinateFrom: mapView)
let southWest = mapView.convert(CGPoint(x: 0, y: mapView.bounds.height), toCoordinateFrom: mapView)

Related

SceneKit camera not moving to proper location

I am working on a solar system swift playground. I want the camera to zoom into a planet if that planet is clicked. The current issue I am having is that the camera won't zoom into the right location. Here is the code I am using.
public let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: -70, z: 50)
camera.eulerAngles = SCNVector3(x: 0.74533, y: 0, z: 0)
let location = planetNodes[i].convertPosition(planetNodes[i].position, to: camera)
let radius = planetNodes[i].position.y
let moveCameraAc = SCNAction.move(to: location, duration: 2)
moveCameraAc.timingMode = .easeInEaseOut
camera.runAction(moveCameraAc)
It will always move to a different location in the scene. I am unable to figure out how is it finding out where to move to.
Thanks in advance!
I have figured it out! The code needs to look like
let location = holderNodes[i].convertPosition(planetNodes[i].position, to: scene.rootNode)
holderNodes[i] is the parent of planetNodes[i] and scene.rootNode is the parent node of camera.

Zoom to fit user location and annotation map view swift

My map view shows both the user location and annotation for the destination mural, but the zoom is off. How can I make it scale to fit the current location and the destination annotation based on how far apart they are and more centered?
This is how it zooms (so far away)
func mapPoints(){
let annotations = MKPointAnnotation()
annotations.title = muralModel.muralName!
muralModel.getMainArtistModel(completion: { (anArtistModel) in
annotations.subtitle = " \(anArtistModel!.firstName!) \(anArtistModel!.lastName!)"
})
annotations.coordinate = coordinates
muralLocation.addAnnotation(annotations)
self.muralLocation.showsUserLocation = true
var zoomRect: MKMapRect = MKMapRectNull
let mapEdgePadding = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
//convert CLLocationCoordinate2D to MKMapPointForCoordinate so you don't end up in Bering Sea
let userPoint = MKMapPointForCoordinate(muralLocation.userLocation.coordinate)
let destinationPoint = MKMapPointForCoordinate(coordinates)
let userPointRect = MKMapRectMake(userPoint.x, userPoint.y, 0.1, 0.1)
let destinationPointRect = MKMapRectMake(destinationPoint.x, destinationPoint.y, 0.1, 0.1)
zoomRect = userPointRect
zoomRect = MKMapRectUnion(zoomRect, destinationPointRect)
muralLocation.setVisibleMapRect(zoomRect, edgePadding: mapEdgePadding, animated: true)
}
You can use the 'func setRegion(_ region: MKCoordinateRegion, animated: Bool)'. MKCoordinateRegion has a center and also defines a span for the region. The center here can be a point at an equal distance from the userLocation and the destination. You can decide the span accordingly.

Swift 3 / current CLLocation inside MKPolygon without CGPath or Mapview

Full disclosure - I'm new here, but I've dug through everything and can't seem to parse together what I need. I'm at the point where Google is only returning purple links.
Is there a way to check user's current CLLocation lat/lon against several MKPolygon's without operating a MapView? Basically just in the background until lat/lon is inside MKPolygon then return a BOOL.
Here's what I have currently.
var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()
points.append(CLLocationCoordinate2DMake(43.8138, -78.8884))
points.append(CLLocationCoordinate2DMake(43.8074, -78.8768))
points.append(CLLocationCoordinate2DMake(43.8130, -78.8688))
points.append(CLLocationCoordinate2DMake(43.8210, -78.8806))
let zoneA: MKPolygon = MKPolygon(coordinates: &points, count: 4)
let point1 = CLLocationCoordinate2D(latitude: 43.8146, longitude: -78.8784)
func contained(by vertices: [CLLocationCoordinate2D]) -> Bool {
let path = CGMutablePath()
for vertex in vertices {
if path.isEmpty
{
path.move(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
}
else
{
path.addLine(to: CGPoint(x: vertex.longitude, y: vertex.latitude))
}
}
let point = CGPoint(x: 43.7146, y: -78.8784)
return path.contains(point)
}

How to create an MKCoordinate region similar to 50 miles radius in ios Swift?

I'm trying to create a region similar to a circle radius using CLLocation. I understand radius logic and how its measured in meters, but not so clear on a MKCoordinate region and how long delta and lat delta translate to area. I would like to get a 75 mile region. Here is my code....
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
If you could please provide an explanation more than just a short answer it would be appreciated.
If you're trying to create an actual circular region:
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let radius: CLLocationDistance = 60350.4 // meters for 37.5 miles
let regionIdentifier = "CircularRegion" // any desired String
let circularRegion = CLCircularRegion(center: center, radius: radius, identifier: regionIdentifier)
You could use MKCoordinateRegionMakeWithDistance function:
Creates a new MKCoordinateRegion from the specified coordinate and
distance values.
func MKCoordinateRegionMakeWithDistance(
_ centerCoordinate: CLLocationCoordinate2D,
_ latitudinalMeters: CLLocationDistance,
_ longitudinalMeters: CLLocationDistance) -> MKCoordinateRegion
centerCoordinate - The center point of the new coordinate region.
latitudinalMeters - The amount of north-to-south distance (measured in meters) to use for the span.
longitudinalMeters - The amount of east-to-west distance (measured in meters) to use for the span.
So you will have something like:
let rect = MKCoordinateRegionMakeWithDistance(center, 50 * 1609.34, 50 * 1609.34)

SpriteKit PhysicsBody is not applying for my bezier curve

Here is the test code:
var paths = UIBezierPath()
var bottomLeft = CGPoint(x: dim.minX, y:dim.minY)
var bottomRight = CGPoint(x: dim.maxX , y: dim.minY )
var topRight = CGPoint(x: dim.maxX, y: dim.maxY )
var topLeft = CGPoint(x: dim.minX, y: dim.maxY)
paths.moveToPoint(bottomRight)
paths.addLineToPoint(topRight)
paths.moveToPoint(topRight)
paths.addLineToPoint(topLeft)
paths.moveToPoint(topLeft)
paths.addLineToPoint(bottomLeft)
paths.moveToPoint(bottomLeft)
paths.addLineToPoint(bottomRight)
var n = SKShapeNode(path: paths.CGPath)
n.strokeColor = UIColor.greenColor()
n.physicsBody = SKPhysicsBody(edgeLoopFromPath: paths.CGPath)
shapeLayer.addChild(n)
It draws a standard rect. I will add some curve in the middle from topRight to topLeft points, but I wanted to test it with simple rect. I am testing the collision with a ball and it seems to be only colliding with the line from bottomRight to topRight and ignoring the rest. Does anyone have a idea on whats going on here?
Although I am not sure about the issue with bezier path and the physics collision setup code needed, I was however able to get it working with using raw paths and adding lines:
var polygonPath = CGPathCreateMutable()
CGPathMoveToPoint(polygonPath, nil, bottomRight.x, bottomRight.y)
CGPathAddLineToPoint(polygonPath, nil, topRight.x, topRight.y)
CGPathAddLineToPoint(polygonPath, nil, topLeft.x, topLeft.y)
CGPathAddLineToPoint(polygonPath, nil, bottomLeft.x, bottomLeft.y)
CGPathCloseSubpath(polygonPath)
var n = SKShapeNode(path: polygonPath)
n.strokeColor = UIColor.grayColor()
n.physicsBody = SKPhysicsBody(edgeLoopFromPath: polygonPath)
That sets up proper physics collision bounds. Although this solves my issue, any insight on why the original code was not working with bezier path would be great. Thanks.