How to convert an ios esri arcGIS Point into latitude and longitude - ios

I have a service return arcgis json format , i want to convert this geometry points to longitude and latitude ios
example :
"geometryType": "esriGeometryPoint",
"geometry": {
"x": 445340.99496,
"y": 2423705.6300004,
"spatialReference": {
"wkid": 32637,
"latestWkid": 32637
}
}
i convert the point
AGSGraphic *testGraphic = [[AGSGraphic alloc] initWithJSON:jsonData] ;
how i can get from AGSGraphic longitude and latitude

this solved the problem , just send xPoint and yPoint and it will return CLLocation Object contain lng and latit
-(CLLocation *) convertToLongAndLat:(double) xPoint andYPoint :(double) yPoint {
double originShift = 2 * M_PI * 6378137 / 2.0;
double lon = (xPoint / originShift) * 180.0;
double lat = (yPoint / originShift) * 180.0;
lat = 180 / M_PI * (2 * atan( exp( lat * M_PI / 180.0)) - M_PI / 2.0);
return [[CLLocation alloc] initWithLatitude:lat longitude:lon];
}

I think that you want to change the spatial reference based on what you want .
Ex :
//AA : Get the clicked point
let gpsPoint = clickedMapPoint
let engine = AGSGeometryEngine.defaultGeometryEngine()
//AA : Change the spatial ref to get real lon and lat
let mapPoint = engine.projectGeometry(gpsPoint, toSpatialReference: AGSSpatialReference.wgs84SpatialReference()) as! AGSPoint

Related

Create perpendicular lat long from single cllocation coordinate of X meter

I have user current location i.e. CLLocation Coordinate (location lat & long) and user is on race track pointing to one direction with the help of user current location i created one region now I want some more race track coordinate(say 2m , 4m , 6m away from race track in perpendicular direction) and the track is 10 m long. Please check the image and the red points are on the track.
Please check this image
/**
* Returns the destination point from initial point having travelled the given distance on the
* given initial bearing (bearing normally varies around path followed).
*
* #param {double} distance - Distance travelled, in same units as earth radius (default: metres).
* #param {double} bearing - Initial bearing in degrees from north.
*
* #returns {CLLocationCoordinate} Destination point.
*/
#define kEarthRadius 6378137
- (CLLocationCoordinate2D)destinationPointWithStartingPoint:(MKMapPoint)initialPoint distance:(double)distance andBearing:(double)bearing {
CLLocationCoordinate2D location = MKCoordinateForMapPoint(initialPoint);
double delta = distance / kEarthRadius;
double omega = [self degreesToRadians:bearing];
double phi1 = [self degreesToRadians:location.latitude];
double lambda1 = [self degreesToRadians:location.longitude];
double phi2 = asin(sin(phi1)*cos(delta) + cos(phi1) * sin(delta) * cos(omega));
double x = cos(delta) - sin(phi1) * sin(phi2);
double y = sin(omega) * sin(delta) * cos(phi1);
double lambda2 = lambda1 + atan2(y, x);
return CLLocationCoordinate2DMake([self radiansToDegrees:phi2], ([self radiansToDegrees:lambda2]+540)%360-180);
}
- (CLLocationCoordinate2D)rhumbDestinationPointForInitialPoint:(MKMapPoint)initialPoint distance:(double)distance andBearing:(double)bearing {
CLLocationCoordinate2D location = MKCoordinateForMapPoint(initialPoint);
double delta = distance / kEarthRadius;
double omega = [self degreesToRadians:bearing];
double phi1 = [self degreesToRadians:location.latitude];
double lambda1 = [self degreesToRadians:location.longitude];
double delta_phi = delta * cos(omega);
double phi2 = phi1 + delta_phi;
// check for some daft bugger going past the pole, normalise latitude if so
if (fabs(phi2) > M_PI / 2) {
phi2 = phi2 > 0 ? M_PI-phi2 : -M_PI-phi2;
}
double delta_gamma = log(tan(phi2/2+M_PI/4)/tan(phi1/2+M_PI/4));
double q = fabs(delta_gamma) > 10e-12 ? delta_phi / delta_gamma : cos(phi1);
double delta_lambda = delta*sin(omega)/q;
double lambda2 = lambda1 + delta_lambda;
return CLLocationCoordinate2DMake([self radiansToDegrees:phi2], ([self radiansToDegrees:lambda2]+540)%360-180);
}
- (double)degreesToRadians:(double)degrees {
return degrees * M_PI / 180.0;
}
- (double)radiansToDegrees:(double)radians {
return radians * 180.0 / M_PI;
}
Adapted from : http://www.movable-type.co.uk/scripts/latlong.html
More information on bearing : https://en.wikipedia.org/wiki/Bearing_(navigation)
And rhumb line : https://en.wikipedia.org/wiki/Rhumb_line

Can't get Panoramio Data with API

I am trying to get panoramio picture around a given coordinate. However always my query returns zero photos. This is the code I am using.
const double WGS84_a = 6378137.0;
const double WGS84_b = 6356752.3;
double Deg2rad(double degrees) {
return degrees * M_PI / 180.0;
}
double Rad2deg(double radians) {
return radians * 180.0 / M_PI;
}
double WGS84EarthRadius(double lat)
{
double An = WGS84_a*WGS84_a * cos(lat);
double Bn = WGS84_b*WGS84_b * sin(lat);
double Ad = WGS84_a * cos(lat);
double Bd = WGS84_b * sin(lat);
return sqrt( (An*An + Bn*Bn)/(Ad*Ad + Bd*Bd) );
}
MapRect LatLonDestPoint(CLLocationCoordinate2D origin, double halfSideInKm) {
double lat = Deg2rad(origin.latitude);
double lon = Deg2rad(origin.longitude);
double halfSide = 1000*halfSideInKm;
double radius = WGS84EarthRadius(lat);
double pradius = radius*cos(lat);
double latMin = lat - halfSide/radius;
double latMax = lat + halfSide/radius;
double lonMin = lon - halfSide/pradius;
double lonMax = lon + halfSide/pradius;
return MKMapRectMake(Rad2deg(latMin), Rad2deg(lonMin), Rad2deg(latMax), Rad2deg(lonMax));
}
Now for a coordinate (60.1190935704,-149.439081366) I get the API like
http://www.panoramio.com/map/get_panoramas.php?set=public&from=0&to=20&minx=60.029034&miny=-149.619843&maxx=60.209152&maxy=-149.258316&size=medium&mapfilter=true
This always returns me zero results. Please help me with what I am doing wrong.
You have x and y coordinates the wrong way around.
Swapping these returns:-
{"count":379,"has_more":true,"map_location":{"lat":60.118290103595498,"lon":-149.45469385385852,"panoramio_zoom":6}
etc
ps Do not rely on the count being correct. Use the has_more flag.

How to calculate the center coordinates of CLLocationDistance

I want calculate the center point between my location and some annotation. So far I have done this:
CLLocation *myLoc = self.locMgr.location;
MKPointAnnotation *middleAnnotation = [locationV.annotations objectAtIndex:locationV.annotations.count/2];
CLLocation *someStuiodLoc = [[CLLocation alloc] initWithLatitude:middleAnnotation.coordinate.latitude longitude:middleAnnotation.coordinate.longitude];
CLLocationDistance dist = [myLoc distanceFromLocation:someStuiodLoc];
How can I calculate the center point/cordinate of "dist" ??
#define ToRadian(x) ((x) * M_PI/180)
#define ToDegrees(x) ((x) * 180/M_PI)
+ (CLLocationCoordinate2D)midpointBetweenCoordinate:(CLLocationCoordinate2D)c1 andCoordinate:(CLLocationCoordinate2D)c2
{
c1.latitude = ToRadian(c1.latitude);
c2.latitude = ToRadian(c2.latitude);
CLLocationDegrees dLon = ToRadian(c2.longitude - c1.longitude);
CLLocationDegrees bx = cos(c2.latitude) * cos(dLon);
CLLocationDegrees by = cos(c2.latitude) * sin(dLon);
CLLocationDegrees latitude = atan2(sin(c1.latitude) + sin(c2.latitude), sqrt((cos(c1.latitude) + bx) * (cos(c1.latitude) + bx) + by*by));
CLLocationDegrees longitude = ToRadian(c1.longitude) + atan2(by, cos(c1.latitude) + bx);
CLLocationCoordinate2D midpointCoordinate;
midpointCoordinate.longitude = ToDegrees(longitude);
midpointCoordinate.latitude = ToDegrees(latitude);
return midpointCoordinate;
}
I have written library function in Swift to calculate the midpoint between multiple coordinates as following:
// /** Degrees to Radian **/
class func degreeToRadian(angle:CLLocationDegrees) -> CGFloat{
return ( (CGFloat(angle)) / 180.0 * CGFloat(M_PI) )
}
// /** Radians to Degrees **/
class func radianToDegree(radian:CGFloat) -> CLLocationDegrees{
return CLLocationDegrees( radian * CGFloat(180.0 / M_PI) )
}
class func middlePointOfListMarkers(listCoords: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D{
var x = 0.0 as CGFloat
var y = 0.0 as CGFloat
var z = 0.0 as CGFloat
for coordinate in listCoords{
var lat:CGFloat = degreeToRadian(coordinate.latitude)
var lon:CGFloat = degreeToRadian(coordinate.longitude)
x = x + cos(lat) * cos(lon)
y = y + cos(lat) * sin(lon);
z = z + sin(lat);
}
x = x/CGFloat(listCoords.count)
y = y/CGFloat(listCoords.count)
z = z/CGFloat(listCoords.count)
var resultLon: CGFloat = atan2(y, x)
var resultHyp: CGFloat = sqrt(x*x+y*y)
var resultLat:CGFloat = atan2(z, resultHyp)
var newLat = radianToDegree(resultLat)
var newLon = radianToDegree(resultLon)
var result:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: newLat, longitude: newLon)
return result
}
Detailed answer can be found here
U can calculate the midPoint of two coordinates using the mid point formula (http://www.purplemath.com/modules/midpoint.htm) which gives a close approximation to the actual geographical point if the distances are lesser than 500 miles. If you consider that the earth is spherical, then a more complex treatment of the points would be involved.

How to find the angular direction to a point in the map (respect to north)

I need to find the angle between the north and a point in a map (21.4167, -39.8167).
here is my code
double MECCA_LONGITUDE = 21.4167;
double MECCA_LATITUDE = -39.8167;
-(void) getAngle :(float) phoneAngle: (float) lon:(float) lat
{
float ad = atan (sin (lon - MECCA_LATITUDE) / ( (cos (lat)) * (tan (MECCA_LATITUDE)) ) - ( (sin (lat)) * (cos (lon - MECCA_LONGITUDE)) ));
NSLog(#"###### %f", CC_RADIANS_TO_DEGREES(ad));
}
I'm still not getting the correct answer. Any tips would be appreciated. Thanks.
Your principle problem is that sin() and cos() take their arguments in radians, and you are passing degrees (you also have the longitude and latitude of Mecca interchanged).
Try:
double MECCA_LATITUDE = 21.4167;
double MECCA_LONGITUDE = 39.8167;
double r_delta_lon = CC_DEGREES_TO_RADIANS(MECCA_LONGITUDE - lon);
double r_lat2 = CC_DEGREES_TO_RADIANS(MECCA_LATITUDE);
double r_lon1 = CC_DEGREES_TO_RADIANS(lon);
double r_lat1 = CC_DEGREES_TO_RADIANS(lat);
double ad = atan2(sin(r_delta_lon) * cos(r_lat2),
cos(r_lat1) * sin(r_lat2) - sin(r_lat1) * cos(r_lat2) * cos(r_delta_lon));

Adding random MKAnnotations around Current Location in a MKMapView

I have an MKMapView that shows the current users location. When I click a button in the navigation bar, I want to randomly drop 10 MKAnnotation pins. These can be dropped anywhere, randomly, but only within the current visible map area and around the current location.
How would go about doing something like this? Is there a way to have a long/lat range that is around the users location, but within the map area? Then, I could randomly choose from this range?
Basically, I need to find what coordinates are available in the current MKCoordinateRegion.
Is there a better way to go about this?
You can get your annotations using the distance between user location and other location
check out below code
#define DISTANCE_RADIUS 10.0 // in KM
-(NSArray *)findNearMe:(NSArray *)lounges {
NSMutableArray *arNearme = [NSMutableArray array];
CLLocation *currentLocation;
for(NSDictionary *d in lounges)
{
currentLocation = [[CLLocation alloc] initWithLatitude:29.33891 longitude:48.077202];
CGFloat latitude=[[d valueForKey:#"latitude"] floatValue];
CGFloat longitude=[[d valueForKey:#"longitude"] floatValue];
CLLocation *newPinLocation=[[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
double distanceValue=[currentLocation distanceFromLocation:newPinLocation];
if(distanceValue/1000.0<=DISTANCE_RADIUS) {
[arNearme addObject:d];
}
}
return arNearme;
}
It will returns you an array of range of 1 to 1000 km near user location.
Used the annotations array and show your annotations in to map view with user location.
I figured it out, here is how I did it:
/**
* Adds new pins to the map
*
* #version $Revision: 0.1
*/
+ (void)addPinsToMap:(MKMapView *)mapView amount:(int)howMany {
//First we need to calculate the corners of the map so we get the points
CGPoint nePoint = CGPointMake(mapView.bounds.origin.x + mapView.bounds.size.width, mapView.bounds.origin.y);
CGPoint swPoint = CGPointMake((mapView.bounds.origin.x), (mapView.bounds.origin.y + mapView.bounds.size.height));
//Then transform those point into lat,lng values
CLLocationCoordinate2D neCoord = [mapView convertPoint:nePoint toCoordinateFromView:mapView];
CLLocationCoordinate2D swCoord = [mapView convertPoint:swPoint toCoordinateFromView:mapView];
// Loop
for (int y = 0; y < howMany; y++) {
double latRange = [MapUtility randomFloatBetween:neCoord.latitude andBig:swCoord.latitude];
double longRange = [MapUtility randomFloatBetween:neCoord.longitude andBig:swCoord.longitude];
// Add new waypoint to map
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(latRange, longRange);
MPin *pin = [[MPin alloc] init];
pin.coordinate = location;
[mapView addAnnotation:pin];
}//end
}//end
/**
* Random numbers
*
* #version $Revision: 0.1
*/
+ (double)randomFloatBetween:(double)smallNumber andBig:(double)bigNumber {
double diff = bigNumber - smallNumber;
return (((double) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + smallNumber;
}//end
In Swift 3.0
func addPins() {
let nePoint = CGPoint(x: mapView.bounds.origin.x + mapView.bounds.size.width, y: mapView.bounds.origin.y)
let sePoint = CGPoint(x: mapView.bounds.origin.x, y: mapView.bounds.origin.y + mapView.bounds.size.height)
let neCoord = mapView.convert(nePoint, toCoordinateFrom: mapView)
let seCoord = mapView.convert(sePoint, toCoordinateFrom: mapView)
var y = 5
while y > 0 {
let latRange = randomBetweenNumbers(firstNum: Float(neCoord.latitude), secondNum: Float(seCoord.latitude))
let longRange = randomBetweenNumbers(firstNum: Float(neCoord.longitude), secondNum: Float(seCoord.longitude))
let location = CLLocationCoordinate2D(latitude: CLLocationDegrees(latRange), longitude: CLLocationDegrees(longRange))
let pin = MKPointAnnotation()
pin.coordinate = location
pin.title = "Home"
mapView.addAnnotation(pin)
y -= 1
}
}
func randomBetweenNumbers(firstNum: Float, secondNum: Float) -> Float{
return Float(arc4random()) / Float(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
swift 4:
// returned coordinates all restricted to the provided bound
// nwCoordinate: north West coordinate of the target bound
// seCoordinate: south east coordinate of the target bound
func createRandomLocation(nwCoordinate: CLLocationCoordinate2D, seCoordinate: CLLocationCoordinate2D) -> [CLLocationCoordinate2D]
{
return (0 ... 30).enumerated().map { _ in
let latitude = randomFloatBetween(nwCoordinate.latitude, andBig: seCoordinate.latitude)
let longitude = randomFloatBetween(nwCoordinate.longitude, andBig: seCoordinate.longitude)
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
}
private func randomFloatBetween(_ smallNumber: Double, andBig bigNumber: Double) -> Double {
let diff: Double = bigNumber - smallNumber
return ((Double(arc4random() % (UInt32(RAND_MAX) + 1)) / Double(RAND_MAX)) * diff) + smallNumber
}

Resources