Direzione GPS bussola iPhone

Sto cercando di sviluppare un’applicazione che utilizzi il GPS e la bussola dell’iPhone per puntare una sorta di puntatore a una posizione specifica (come la bussola punta sempre verso nord). La posizione è fissa e ho sempre bisogno del puntatore per puntare a quella posizione specifica, indipendentemente da dove si trovi l’utente. Ho le coordinate Lat / Long di questa posizione, ma non sono sicuro di come posso indicare quella posizione utilizzando la bussola e il GPS … proprio come http://www.youtube.com/watch?v=iC0Xn8hY80w questo link 1: 20′

Scrivo un codice, tuttavia, non può ruotare nella giusta direzione.

-(float) angleToRadians:(double) a { return ((a/180)*M_PI); } -(void)updateArrow { double alon=[longi doubleValue];//source double alat=[lati doubleValue];//source double blon=[pointlongi doubleValue];//destination double blat=[pointlati doubleValue];//destination float fLat = [self angleToRadians:alat]; float fLng = [self angleToRadians:alon]; float tLat = [self angleToRadians:blat]; float tLng = [self angleToRadians:blon]; float temp = atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)); double temp2= previousHeading; double temp1=temp-[self angleToRadians:temp2]; /*I using this,but it can't rotate by :point even i change the coordinate in CGPointMake */ Compass2.layer.anchorPoint=CGPointMake(0, 0.5); [Compass2 setTransform:CGAffineTransformMakeRotation(temp1)]; /* Compass2 is a UIImageView like below picture I want to rotate it around : point in image ^ | | | : | */ 

Esiste un’equazione standard “heading” o “bearing” che puoi usare – se sei a lat1, lon1, e il punto a cui sei interessato è lat2, lon2, allora l’equazione è:

 heading = atan2( sin(lon2-lon1)*cos(lat2), cos(lat1)*sin(lat2) - sin(lat1)*cos(lat2)*cos(lon2-lon1)) 

Questo ti dà una misura in radianti, che puoi convertire in gradi moltiplicando per 180 / π. Il valore è quindi compreso tra -180 e 180 gradi, quindi per ottenere una bussola standard aggiungere 360 ​​a qualsiasi risposta negativa.

atan2 è una funzione standard relativa all’arctan, che fa la cosa giusta per i quattro possibili quadranti che il tuo punto di destinazione potrebbe essere rispetto a dove ti trovi.

1) Ottieni la tua posizione attuale (dal GPS)

2) Ottieni le differenze di latitudine e longitudine

3) usa il metodo atan2 per ottenere l’angolo

cioè (ATTENZIONE: codice non testato)

 CLLocation *targetLocation = [CLLocation alloc] initWithLatitude:1 longitude:2]; CLLocation *sourceLocation =  double dx = [targetLocation coordinate].latitude - [sourceLocation coordinate].latitude; double dy = [targetLocation coordinate].longitude - [sourceLocation coordinate].longitude; double angle = atan2(dx, dy); 

Potrebbe essere necessario modificarlo per farlo compilare, ma l’idea è lì!

L’ho fatto qualche tempo fa, qui ci sono due diverse implementazioni. Il primo è simile al tuo approccio, il secondo è senza matematica trigonometrica. Il primo è quello che ho usato nella mia app, ma il secondo sembrava funzionare altrettanto bene, anche se non sembra essere pulito. Dovrai anche ricordarti di spostare questo cuscinetto sulla base del nord nell’interfaccia utente.

 - (double) toRadian: (double) val { return val * (M_PI / 180); } // Convert to degrees from radians - (double) toDegrees: (double) val { return val * 180 / M_PI; } // convert from a radian to a 360 degree format. - (double) toBearing: (double) val { return ( (int)([self toDegrees: val]) + 360 ) % 360; // use mod to get the degrees } // Calculate the bearing based off of the passed coordinates and destination. // - (double) calcBearingWithLatitude:(CLLocationDegrees)latSource latitude:(CLLocationDegrees)latDest longitude:(CLLocationDegrees)lonSrc longitude:(CLLocationDegrees)lonDest { double lat1 = [self toRadian:latSource]; double lat2 = [self toRadian:latDest]; double dLon = [self toRadian:(lonDest - lonSrc)]; double y = sin(dLon) * cos(lat2); double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon); return [self toBearing:atan2(y, x)]; } 

E il secondo.

 // got this code from some forums and modified it, thanks for posting it coullis! Mostly here for reference on how to do this without sin and cos. - (CLLocationDegrees) altCalcBearingWithLatitude:(CLLocationDegrees)latSource latitude:(CLLocationDegrees)latDest longitude:(CLLocationDegrees)lonSrc longitude:(CLLocationDegrees)lonDest { CLLocationDegrees result; // First You calculate Delta distances. float dx = lonSrc - latSource; float dy = lonDest - latDest; // If x part is 0 we could get into division by zero problems, but in that case result can only be 90 or 270: if (dx==0) { if (dy > 0) result = 90; else result = 270; } else { result = [self toDegrees: atan(dy/dx)]; } // This is only valid for two quadrants (for right side of the coordinate system) so modify result if necessary... if (dx < 0) result = result + 180; // looks better if all numbers are positive (0 to 360 range) if (result < 0) result = result + 360; // return our result. return result; 

}

Usa questo. Dovrai sottrarre la tua vera bussola dal risultato di getHeadingForDirection per determinare la corretta intestazione relativa. Il valore di ritorno è in radianti .

 -(float) angleToRadians:(float) a { return ((a/180)*M_PI); } - (float) getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc { float fLat = [self angleToRadians:fromLoc.latitude]; float fLng = [self angleToRadians:fromLoc.longitude]; float tLat = [self angleToRadians:toLoc.latitude]; float tLng = [self angleToRadians:toLoc.longitude]; return atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)); }