羅盤,估計也不用我過多介紹,學過國中實體的都知道,不管是指南針,還是指北針,其本質就是用來辨識方向的。
操作電子羅盤偉感器也不複雜,主要就是兩個角度:
1、目前方向與磁北的夾角;
2、目前方向與地北的夾角。
同時,我們也了解到,地理北極與地磁北極并不是重合的,存在地偏角。在讀取電子羅盤資料時,可以優先考慮讀取與地北極的夾角,如果讀不到地北極的夾角,再讀取磁北極的夾角資料。
CompassReading類(位于Windows.Devices.Sensors命名空間)封裝了從電子羅盤所讀到的資料。
1、HeadingMagneticNorth屬性:擷取目前方向與磁北的夾角度數。
2、HeadingTrueNorth屬性:該屬性擷取的是真北夾角,即地理夾角。我們注意到它的類型為double?,即Nullable<double>,表明這個數值有可能為null,也就是說有可能擷取不到地北夾角的值。在使用時,我們可以先判斷地北角是否為null,如不為null就用這個值;如果為null就用磁北角的值。
3、HeadingAccuracy屬性:表示羅盤讀數的準确性,如果讀數精度較高,其傳回High。我們的應用程式可以在合适的時候檢查這個屬性是否為High,如果不是,可以考慮提示使用者校準羅盤。
提到校準,不得不說一下的是,校準羅盤是不需要系統提示,應用也可以不提示。隻是考慮到使用者體驗的問題,可以提示使用者校準。校準方法很簡單,不管你是使用WP自帶的地圖應用,還是其他第三方應用,或者你自己開發的應用。隻要在使用到羅盤的地方,你拿着手機,在空中做幾次“8”字形來回移動就可以了,不需要等待提示,隻要在用到羅盤的地方就可以随時校準。
電子羅盤的API封裝在Windows.Devices.Sensors.Compass類中,WP API中的所有傳感器調用都很簡單,首先擷取到某個傳感器類的執行個體,一般通過GetDefault方法(靜态方法)就能傳回,然後設定讀取的時間間隔,以毫秒為機關,如果你希望每秒讀一次資料,就把ReportInterval設定為1000,但是,這個時間間隔不能小于MinimumReportInterval屬性指定的值,這個要注意,設定為20毫秒以上的間隔,效果都不錯了,當然這要看你使用的實際情況了。
最後處理ReadingChanged事件,當有新的資料讀到時,會引發該事件,并把新讀到的資料傳遞給該事件,我們就可以從事件參數中擷取最新的讀數。
好了,理論永遠都是抽象的,下面給大家看一下我做的一個簡陋指南針,确實很簡,希望大家莫笑,因為本人較菜,是以連首頁上的羅盤也是用XAML直接畫的。
先上一個效果圖。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuQzM3EDOygDN1cDMxEjMw8CX5ADNxAjMvwVO4MzN2MzLcd2bsJ2Lc12bj5ycn9Gbi52YuAzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
看吧,簡陋吧,沒辦法,人窮就是這樣,要簡食素衣。指南針背景我是用幾個圈圈畫的,訓示方向的指針是用Path元素畫的。
原理是這樣的:
根據電子羅盤讀到的角度,對紅色的指針對象進行旋轉變換——就是用RotateTransform類來旋轉。但要注意旋轉的角度。比如,我目前方向是20度,即東北偏北方向,那麼,要怎麼設定角度才能保證紅色的指針始終指向南方呢。
我們知道,夾角是以正北為參考的,如果要使指針指向南方,一種方法是将羅盤讀到的角度加上180,因為南北的夾角正好是180度(平角);另一種方法是,讓指針的初始位置向下,即指向正南方,我就是用這個方法的。如圖。
不管是指向北方還是南方(上北下南),都可以按相同的角度來旋轉,因為它們的夾角正好是180。
于是,第二個問題産生了——要旋轉多少度才合适?我們上面舉例說目前方向為20度,參照标準是北極,也就是說此時我們的手機已經偏向20度方向,如果把指針旋轉20度,那麼指針相對于螢幕,偏轉的角度就是40度了,本來就偏了20度,你再轉20度,就番倍了,顯然這樣不妥,我們必須把這個角度差抵消掉。
也就是說,如果我目前方向是20度,那麼指針的旋轉變換應為-20度,這樣才能把偏差的角度補平,不然的話,你試試就知道了,如果不抵消的話,指針會越走越偏。
還有一種方法就是用360度作為被減數,如360 - 20 = 340度,-20度和340度雖然計算方向不同,但它們的位置是相同的。是以兩種方法都可以。比如讀數是80度,可以把指針旋轉-80度,也可以旋轉360 - 80度。
async void _compass_ReadingChanged ( Compass sender, CompassReadingChangedEventArgs args )
{
var res = args.Reading;
// 如果地北極的偏角值不可用,則使用磁北極角度
double val = res.HeadingTrueNorth ?? res.HeadingMagneticNorth;
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
// 如果精度較高,則停止校準
if (isChecking && res.HeadingAccuracy == MagnetometerAccuracy.High)
{
fly.Hide();
isChecking = false;
}
// 旋轉的方向是羅盤角度的負值
rotatTransform.Angle = -val;
Display(val);
});
}
Display方法是我自定義的方法,用來判斷讀數所指的方向,并在頁面上以文本的方式顯示。比如,讀數為0,就是“正北”,讀數為180度,為“正南”等。
/// <summary>
/// 顯示方位
/// </summary>
private void Display ( double v )
{
string d = "";
int ind = Convert.ToInt32(v);
if (ind == 0 || ind == 360)
{
d = "正北";
}
else if (ind == 90)
{
d = "正東";
}
else if (ind == 180)
{
d = "正南";
}
else if (ind == 270)
{
d = "正西";
}
else if (ind > 0 && ind < 90)
{
d = "東北";
}
else if (ind > 90 && ind < 180)
{
d = "東南";
}
else if (ind > 180 && ind < 270)
{
d = "西南";
}
else if (ind > 270 && ind < 360)
{
d = "西北";
}
tbW.Text = string.Format("{0}°({1})", ind, d);
}
以上所列是重點的代碼片段,其他代碼大家可以參考我上傳的示例源代碼。
下載下傳位址:https://files.cnblogs.com/tcjiaan/CompassApp.zip