ios - Centering MKMapView on spot N-pixels below pin -


want center mkmapview on point n-pixels below given pin (which may or may not visible in current maprect).

i've been trying solve using various plays -(cllocationcoordinate2d)convertpoint:(cgpoint)point tocoordinatefromview:(uiview *)view no success.

anyone been down road (no pun intended)?

enter image description here

the easiest technique shift map down, 40% coordinate be, taking advantage of span of region of mkmapview. if don't need actual pixels, need move down cllocationcoordinate2d in question near top of map (say 10% away top):

cllocationcoordinate2d center = coordinate; center.latitude -= self.mapview.region.span.latitudedelta * 0.40; [self.mapview setcentercoordinate:center animated:yes]; 

if want account rotation , pitch of camera, above technique may not adequate. in case, could:

  • identify position in view want shift user location;

  • convert cllocation;

  • calculate distance of current user location new desired location;

  • move camera distance in direction 180° current heading of map's camera.

e.g. in swift 3, like:

var point = mapview.convert(mapview.centercoordinate, topointto: view) point.y -= offset let coordinate = mapview.convert(point, tocoordinatefrom: view) let offsetlocation = coordinate.location  let distance = mapview.centercoordinate.location.distance(from: offsetlocation) / 1000.0  let camera = mapview.camera let adjustedcenter = mapview.centercoordinate.adjust(by: distance, at: camera.heading - 180.0) camera.centercoordinate = adjustedcenter 

where cllocationcoordinate2d has following extension:

extension cllocationcoordinate2d {     var location: cllocation {         return cllocation(latitude: latitude, longitude: longitude)     }      private func radians(from degrees: cllocationdegrees) -> double {         return degrees * .pi / 180.0     }      private func degrees(from radians: double) -> cllocationdegrees {         return radians * 180.0 / .pi     }      func adjust(by distance: cllocationdistance, @ bearing: cllocationdegrees) -> cllocationcoordinate2d {         let distanceradians = distance / 6_371.0   // 6,371 = earth's radius in km         let bearingradians = radians(from: bearing)         let fromlatradians = radians(from: latitude)         let fromlonradians = radians(from: longitude)          let tolatradians = asin( sin(fromlatradians) * cos(distanceradians)             + cos(fromlatradians) * sin(distanceradians) * cos(bearingradians) )          var tolonradians = fromlonradians + atan2(sin(bearingradians)             * sin(distanceradians) * cos(fromlatradians), cos(distanceradians)                 - sin(fromlatradians) * sin(tolatradians))          // adjust tolonradians in range -180 +180...         tolonradians = fmod((tolonradians + 3.0 * .pi), (2.0 * .pi)) - .pi          let result = cllocationcoordinate2d(latitude: degrees(from: tolatradians), longitude: degrees(from: tolonradians))          return result     } } 

so, camera pitched , @ heading other due north, moves user's location (which centered, lower crosshair is) 150 pixels (where upper crosshair is), yielding like:

enter image description here

obviously, should conscious degenerate situations (e.g. you're 1 km south pole , try shift map 2 km meters; you're using camera angle pitched far desired screen location past horizon; etc.), practical, real-world scenarios, above might sufficient. obviously, if don't let user change pitch of camera, answer easier.


original answer: moving annotation n pixels

if have cllocationcoordinate2d, can convert cgpoint, move x pixels, , convert cllocationcoordinate2d:

- (void)movecenterbyoffset:(cgpoint)offset from:(cllocationcoordinate2d)coordinate {     cgpoint point = [self.mapview convertcoordinate:coordinate topointtoview:self.mapview];     point.x += offset.x;     point.y += offset.y;     cllocationcoordinate2d center = [self.mapview convertpoint:point tocoordinatefromview:self.mapview];     [self.mapview setcentercoordinate:center animated:yes]; } 

you can call by:

[self movecenterbyoffset:cgpointmake(0, 100) from:coordinate]; 

unfortunately, works if coordinate visible before start, might have go original coordinate first, , adjust center.


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -