Android में स्थान पर कंपास असर/शीर्षक की गणना करें




location compass-geolocation (8)

मैं अपने मानचित्र पर एक Google मानचित्र दृश्य पर एक तीर प्रदर्शित करना चाहता हूं जो गंतव्य स्थान (उत्तर की बजाय) से संबंधित मेरी दिशा प्रदर्शित करता है।

ए) मैंने मैग्नेटोमीटर और एक्सेलेरोमीटर से सेंसर मूल्यों का उपयोग करके उत्तर की गणना की है। मुझे पता है कि यह सही है क्योंकि यह Google मानचित्र दृश्य पर उपयोग किए गए कंपास के साथ लाइन करता है।

बी) मैंने myLocation.bearingTo (destLocation) का उपयोग करके मेरे स्थान से गंतव्य स्थान पर प्रारंभिक असर की गणना की है;

मुझे आखिरी कदम याद आ रहा है; इन दो मूल्यों से (ए और बी) मैं उस स्थान को प्राप्त करने के लिए किस सूत्र का उपयोग करता हूं जिसमें फ़ोन गंतव्य स्थान के सापेक्ष इंगित कर रहा है?

एक मिश्रित दिमाग के लिए किसी भी मदद की सराहना करते हैं!


@ डेमियन - विचार बहुत अच्छा है और मैं जवाब से सहमत हूं, लेकिन जब मैंने आपके कोड का उपयोग किया तो मेरे पास गलत मूल्य थे, इसलिए मैंने इसे स्वयं लिखा (किसी ने आपकी टिप्पणियों में यही कहा)। गिरावट के साथ शीर्षक की गणना करना अच्छा है, मुझे लगता है, लेकिन बाद में मैंने ऐसा कुछ इस्तेमाल किया:

heading = (bearing - heading) * -1;

डेमियन के कोड के बजाय:

heading = myBearing - (myBearing + heading); 

और 0 से 360 के लिए -180 से 180 बदलना:

      private float normalizeDegree(float value){
          if(value >= 0.0f && value <= 180.0f){
              return value;
          }else{
              return 180 + (180 + value);
          }

और फिर जब आप अपने तीर को घुमाने के लिए चाहते हैं तो आप इस तरह के कोड का उपयोग कर सकते हैं:

      private void rotateArrow(float angle){

            Matrix matrix = new Matrix();
            arrowView.setScaleType(ScaleType.MATRIX);
            matrix.postRotate(angle, 100f, 100f);
            arrowView.setImageMatrix(matrix);
      }

जहां arrowView ImageView arrowView साथ ImageView postRotate है और postRotate में 100f पैरामीटर pivX और pivY है)।

मुझे आशा है कि मैं किसी की मदद करूंगा।


इसमें कंपास पर एक तीर आपके स्थान से दिशा का स्थान दिखाता है ( गंतव्य स्थान )

आप इस तरह से असर का उपयोग कर सकते हैं। आपको अपने स्थान से गंतव्य स्थान पर सीधे कोण प्रदान करने के लिए तैयार किया जाएगा

  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);

असर आपको -180 से 180 तक की रेंज देगा, जो चीजों को थोड़ा उलझन में डाल देगा। सही रोटेशन प्राप्त करने के लिए हमें इस मान को 0 से 360 तक एक श्रेणी में बदलने की आवश्यकता होगी।

यह वास्तव में क्या चाहते हैं की एक सारणी है, जो हमें बताती है कि हमें क्या असर पड़ता है

+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0         | 0            |
+-----------+--------------+
| 90        | 90           |
+-----------+--------------+
| 180       | 180          |
+-----------+--------------+
| -90       | 270          |
+-----------+--------------+
| -135      | 225          |
+-----------+--------------+
| -180      | 180          |
+-----------+--------------+

तो हमें भालू के बाद इस कोड को जोड़ना होगा

// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.

  if (bearTo < 0) {
    bearTo = bearTo + 360;
    //bearTo = -100 + 360  = 260;
}

आपको सेंसरइवेंट लिस्टनर और उसके कार्यों को लागू करने की आवश्यकता है (ऑन सेंसर चेंज, ऑन ऑक्रैरिसी कैबेज) और सेंसर चेंजड के अंदर सभी कोड लिखें

क्यूबाला कंपास की दिशा के लिए पूरा कोड यहां है

 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) {


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 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>

दो बिंदुओं के बीच असर कोण की गणना करने के लिए कोड यहां दिया गया है:

public float CalculateBearingAngle(double lat1,double lon1, double lat2, double lon2){
    double Phi1 = Math.toRadians(lat1);
    double Phi2 = Math.toRadians(lat2);
    double DeltaLambda = Math.toRadians(lon2 - lon1);
    double Theta = atan2((sin(DeltaLambda)*cos(Phi2)),
        (cos(Phi1)*sin(Phi2) - sin(Phi1)*cos(Phi2)*cos(DeltaLambda)));
    return (float)Math.toDegrees(Theta);
}

फ़ंक्शन के लिए कॉल करें:

float angle = CalculateBearingAngle(lat1, lon1, lat2, lon2);

फॉर्मूला अंत बिंदु see के प्रारंभ बिंदु के समन्वय का उपयोग करके असर देगा

निम्नलिखित कोड आपको असर देगा (0-360 के बीच कोण)

private double bearing(Location startPoint, Location endPoint) {
    double longitude1 = startPoint.getLongitude();
    double latitude1 = Math.toRadians(startPoint.getLatitude());

    double longitude2 = endPoint.getLongitude();        
    double latitude2 = Math.toRadians(endPoint.getLatitude());

    double longDiff = Math.toRadians(longitude2 - longitude1);

    double y = Math.sin(longDiff) * Math.cos(latitude2);
    double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff);

    return Math.toDegrees(Math.atan2(y, x));

}

यह मेरे लिए काम करता है उम्मीद है कि यह किसी को भी खोजने के लिए काम करेगा


मैं अब इसे समझने की प्रक्रिया में हूं लेकिन ऐसा लगता है कि गणित इस बात पर निर्भर करता है कि आप और आपका लक्ष्य पृथ्वी पर सत्य और चुंबकीय उत्तर के सापेक्ष हैं। उदाहरण के लिए:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) > myLocation.getBearing()){ 
     thetaMeThem = myLocation.bearingTo(targetLocation) - azimuth + declination;} 

Azimuth के लिए सेंसर.TYPE_ORIENTATION देखें।

गिरावट के लिए getDeclination () देखें

यह मानता है कि गिरावट ऋणात्मक है (सच्चे उत्तर की पश्चिम) और उनकी असर> आपकी असर।

यदि गिरावट सकारात्मक है और आपकी असर> उनके दूसरे विकल्प का पालन करना:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) < myLocation.getBearing()){ 
     thetaMeThem = azimuth - (myLocation.bearingTo(targetLocation) - declination);} 

मैंने पूरी तरह से इसका परीक्षण नहीं किया है लेकिन कागज पर कोणों के साथ खेलना मुझे यहां मिला है।


मैं मानचित्र-पढ़ने / नेविगेशन में कोई विशेषज्ञ नहीं हूं और इसलिए निश्चित रूप से 'दिशानिर्देश' पूर्ण हैं और रिश्तेदार नहीं हैं या वास्तविकता में, वे एन या एस के सापेक्ष हैं जो स्वयं निश्चित / पूर्ण हैं।

उदाहरण: मान लीजिए कि आपके और आपके गंतव्य के बीच खींची गई एक काल्पनिक रेखा 'पूर्ण' एसई (चुंबकीय एन से संबंधित 135 डिग्री के असर) के अनुरूप है। अब मान लीजिए कि आपका फोन एनडब्लू को इंगित कर रहा है - यदि आप अपने गंतव्य पर क्षितिज पर एक काल्पनिक वस्तु से एक काल्पनिक रेखा खींचते हैं, तो यह आपके स्थान से गुज़र जाएगा और 180 डिग्री का कोण होगा। अब एक कंपास की भावना में 180 डिग्री वास्तव में एस को संदर्भित करता है लेकिन गंतव्य काल्पनिक ऑब्जेक्ट का 'देय एस' नहीं है जो आपका फोन इंगित कर रहा है और इसके अलावा, यदि आप उस काल्पनिक बिंदु पर जाते हैं, तो आपका गंतव्य अभी भी एसई होगा जहां आप चले गए।

हकीकत में, 180 डिग्री लाइन वास्तव में आपको बताती है कि फोन (और संभवतः आप) इंगित करने के तरीके के संबंध में गंतव्य आपके पीछे है।

ऐसा कहा जाता है कि, हालांकि, यदि आपके गंतव्य की ओर एक सूचक आकर्षित करने के लिए काल्पनिक बिंदु से आपके गंतव्य (आपके स्थान से गुजरना) से किसी रेखा के कोण की गणना करना आप चाहते हैं ... बस (पूर्ण) असर को घटाएं काल्पनिक वस्तु के पूर्ण असर से गंतव्य और एक अस्वीकृति को अनदेखा करें (यदि मौजूद है)। उदाहरण के लिए, एनडब्ल्यू - एसई 315 - 135 = 180 है इसलिए पॉइंटर को स्क्रीन के नीचे इंगित करने के लिए 'आपके पीछे' इंगित करें।

संपादित करें: मुझे गणित थोड़ा गड़बड़ हो गया है ... बड़े पैमाने पर बीयरिंग के छोटे से घटाएं, फिर स्क्रीन पर पॉइंटर खींचने के कोण को प्राप्त करने के लिए 360 से परिणाम घटाएं।


यहां बताया गया है कि मैंने इसे कैसे किया है:

Canvas g = new Canvas( compass );
Paint p = new Paint( Paint.ANTI_ALIAS_FLAG );

float rotation = display.getOrientation() * 90;

g.translate( -box.left, -box.top );
g.rotate( -bearing - rotation, box.exactCenterX(), box.exactCenterY() );
drawCompass( g, p );
drawNeedle( g, p );

शब्दावली: TRUE उत्तर और चुंबकीय उत्तर के बीच का अंतर "भिन्नता" के रूप में जाना जाता है जो अस्वीकार नहीं होता है। आपके कंपास को पढ़ने के बीच का अंतर और चुंबकीय शीर्षक को "विचलन" के रूप में जाना जाता है और शीर्षक के साथ भिन्न होता है। एक कंपास स्विंग डिवाइस त्रुटियों की पहचान करता है और यदि डिवाइस में सुधार हुआ है तो सुधारों को लागू करने की अनुमति देता है। एक चुंबकीय कंपास में एक विचलन कार्ड होगा जो किसी भी शीर्षक पर डिवाइस त्रुटि का वर्णन करता है।

अस्वीकरण: एस्ट्रो नेविगेशन में इस्तेमाल किया जाने वाला एक शब्द: अस्वीकरण अक्षांश की तरह है। यह रिपोर्ट करता है कि खगोलीय भूमध्य रेखा से एक सितारा कितना दूर है। एक स्टार की गिरावट को खोजने के लिए तार से खगोलीय भूमध्य रेखा तक "सीधे नीचे" एक घंटा सर्कल का पालन करें। घंटे के चक्र के साथ तार से खगोलीय भूमध्य रेखा तक कोण स्टार की गिरावट है।





bearing