I am very keen on knowing an universal qibla direction logic as I want to implement in my islamic android app. I have just obtained latitude and longitude of the user and irrespective of any lat, lon I want to find qibla direction for that person whether the person is in UK, US, India, Sri Lanka or any where.
I found this formula, and don't know how exactly it works:
float lonDelta = (lon2 - lon1);
float y = Math.sin(lonDelta) * Math.cos(lat2);
float x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lonDelta);
float brng = Math.atan2(y, x).toDeg();
Please help me in knowing exact formula.
Qibla Finder shows you the Qibla from your smartphone, in your environment. Finding the Qibla -- the direction that should be faced when a Muslim prays, wherever they are in the world -- is now easier thanks to a new Google web app for Android.
Get Qibla location, Nearest Mosque, Hijri calendar and 99 names of Allah with this Qibla finder app. This is the best Mecca finder app for android. Download the Mecca compass app now to find the direction of Qibla accurately. Qibla compass with GPS will find Kaaba direction very easily and faster.
instead of using this formula
float lonDelta = (lon2 - lon1);
float y = Math.sin(lonDelta) * Math.cos(lat2);
float x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lonDelta);
float brng = Math.atan2(y, x).toDeg();
you can simple use bearingTo in this way
Location userLoc=new Location("service Provider");
//get longitudeM Latitude and altitude of current location with gps class and set in userLoc
userLoc.setLongitude(longitude);
userLoc.setLatitude(latitude);
userLoc.setAltitude(altitude);
Location destinationLoc = new Location("service Provider");
destinationLoc.setLatitude(21.422487); //kaaba latitude setting
destinationLoc.setLongitude(39.826206); //kaaba longitude setting
float bearTo=userLoc.bearingTo(destinationLoc);
bearingTo will give you a range from -180 to 180, which will confuse things a bit. We will need to convert this value into a range from 0 to 360 to get the correct rotation.
This is a table of what we really want, comparing to what bearingTo gives us
+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0 | 0 |
+-----------+--------------+
| 90 | 90 |
+-----------+--------------+
| 180 | 180 |
+-----------+--------------+
| -90 | 270 |
+-----------+--------------+
| -135 | 225 |
+-----------+--------------+
| -180 | 180 |
+-----------+--------------+
so we have to add this code after bearTo
// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.
if (bearTo < 0) {
bearTo = bearTo + 360;
//bearTo = -100 + 360 = 260;
}
you need to implements the SensorEventListener and its functions(onSensorChanged,onAcurracyChabge) and write all the code inside onSensorChanged
Complete code is here for Direction of Qibla compass
public class QiblaDirectionCompass extends Service implements SensorEventListener{
public static ImageView image,arrow;
// record the compass picture angle turned
private float currentDegree = 0f;
private float currentDegreeNeedle = 0f;
Context context;
Location userLoc=new Location("service Provider");
// device sensor manager
private static SensorManager mSensorManager ;
private Sensor sensor;
public static TextView tvHeading;
public QiblaDirectionCompass(Context context, ImageView compass, ImageView needle,TextView heading, double longi,double lati,double alti ) {
image = compass;
arrow = needle;
// TextView that will tell the user what degree is he heading
tvHeading = heading;
userLoc.setLongitude(longi);
userLoc.setLatitude(lati);
userLoc.setAltitude(alti);
mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if(sensor!=null) {
// for the system's orientation sensor registered listeners
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);//SensorManager.SENSOR_DELAY_Fastest
}else{
Toast.makeText(context,"Not Supported", Toast.LENGTH_SHORT).show();
}
// initialize your android device sensor capabilities
this.context =context;
@Override
public void onCreate() {
// TODO Auto-generated method stub
Toast.makeText(context, "Started", Toast.LENGTH_SHORT).show();
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); //SensorManager.SENSOR_DELAY_Fastest
super.onCreate();
}
@Override
public void onDestroy() {
mSensorManager.unregisterListener(this);
Toast.makeText(context, "Destroy", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
float degree = Math.round(sensorEvent.values[0]);
float head = Math.round(sensorEvent.values[0]);
float bearTo;
Location destinationLoc = new Location("service Provider");
destinationLoc.setLatitude(21.422487); //kaaba latitude setting
destinationLoc.setLongitude(39.826206); //kaaba longitude setting
float bearTo=userLoc.bearingTo(destinationLoc);
//bearTo = The angle from true north to the destination location from the point we're your currently standing.(asal image k N se destination taak angle )
//head = The angle that you've rotated your phone from true north. (jaise image lagi hai wo true north per hai ab phone jitne rotate yani jitna image ka n change hai us ka angle hai ye)
GeomagneticField geoField = new GeomagneticField( Double.valueOf( userLoc.getLatitude() ).floatValue(), Double
.valueOf( userLoc.getLongitude() ).floatValue(),
Double.valueOf( userLoc.getAltitude() ).floatValue(),
System.currentTimeMillis() );
head -= geoField.getDeclination(); // converts magnetic north into true north
if (bearTo < 0) {
bearTo = bearTo + 360;
//bearTo = -100 + 360 = 260;
}
//This is where we choose to point it
float direction = bearTo - head;
// If the direction is smaller than 0, add 360 to get the rotation clockwise.
if (direction < 0) {
direction = direction + 360;
}
tvHeading.setText("Heading: " + Float.toString(degree) + " degrees" );
RotateAnimation raQibla = new RotateAnimation(currentDegreeNeedle, direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
raQibla.setDuration(210);
raQibla.setFillAfter(true);
arrow.startAnimation(raQibla);
currentDegreeNeedle = direction;
// create a rotation animation (reverse turn degree degrees)
RotateAnimation ra = new RotateAnimation(currentDegree, -degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// how long the animation will take place
ra.setDuration(210);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
image.startAnimation(ra);
currentDegree = -degree;
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
xml code is here
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/flag_pakistan">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/heading"
android:textColor="@color/colorAccent"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:layout_marginTop="20dp"
android:text="Heading: 0.0" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/heading"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
<ImageView
android:id="@+id/imageCompass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="@drawable/images_compass"/>
<ImageView
android:id="@+id/needle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:scaleType="centerInside"
android:src="@drawable/arrow2"/>
</RelativeLayout>
</RelativeLayout>
Use following method to get accurate qibla direction.
public double calculateQibla(double latitude, double longitude){
double phiK = 21.4 * Math.PI / 180.0;
double lambdaK = 39.8 * Math.PI/180.0;
double phi = latitude*Math.PI/180.0;
double lambda = longitude*Math.PI/180.0;
double psi = 180.0/Math.PI * Math.atan2(Math.sin(lambdaK-lambda),Math.cos(phi)*Math.tan(phiK)-Math.sin(phi)*Math.cos(lambdaK-lambda));
return Math.round(psi);
}
Hope it helps !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With