最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# 基于GMap.NET實(shí)現(xiàn)電子圍欄功能(WPF版)

 更新時(shí)間:2021年03月09日 11:45:01   作者:源之緣  
這篇文章主要介紹了c# 基于GMap.NET實(shí)現(xiàn)電子圍欄功能(WPF版),幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下

前言 

GMap.NET是一個(gè)強(qiáng)大、免費(fèi)、跨平臺(tái)、開源的.NET控件。分為WPF和winform版。GMap.NET的基本知識(shí)不做過多介紹,本文主要介紹如何使用該控件實(shí)現(xiàn)電子圍欄功能。

電子圍欄主要有兩個(gè)功能模塊:界面展示圍欄區(qū)域,判斷人員出入圍欄的邏輯。GMap.NET的WPF版本功能并不強(qiáng)大,實(shí)現(xiàn)一些復(fù)雜的功能就只能發(fā)掘WPF的潛力了。GMap.NET給我們提供了一個(gè)基本的平臺(tái),必須熟練掌握WPF才能開發(fā)出復(fù)雜gis產(chǎn)品。

圍欄區(qū)域界面顯示

1 認(rèn)識(shí) GMapMarker

  GMapControl是地圖的主容器;地圖就是多個(gè)圖片拼接而來,這個(gè)圖片組成GMapControl的底圖。底圖之上點(diǎn)綴用戶自定義的控件。用戶自定義控件必須通過GMapMarker間接添加進(jìn)來,看下面代碼:

GMapMarker maker = new GMapMarker(ptLatLng);
 //UserControlFence用戶自定控件
 _ctrlCurrentFence = new UserControlFence() { Marker = maker, MapCtrl = MainMap };
 _ctrlCurrentFence.FenceInfo = CreateFenceInfoModel();

 maker.Shape = _ctrlCurrentFence;
 this.MainMap.Markers.Add(maker);

GMapMarker 的定義也不復(fù)雜:

public class GMapMarker : INotifyPropertyChanged
{
    public object Tag;
 
    public GMapMarker(PointLatLng pos);
 
    public UIElement Shape { get; set; }
    public PointLatLng Position { get; set; }
    public GMapControl Map { get; }
    public Point Offset { get; set; }
    public int LocalPositionX { get; }
    public int LocalPositionY { get; }
    public int ZIndex { get; set; }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    public virtual void Clear();
    protected void OnPropertyChanged(string name);
    protected void OnPropertyChanged(PropertyChangedEventArgs name);
}

一個(gè)GMapMarker關(guān)聯(lián)一個(gè)gps坐標(biāo),同時(shí)可以顯示一個(gè)控件(Shape );為什么在Shape外面包含一個(gè)marker?maker主要功能就是將控件釘?shù)紾MapControl的一個(gè)點(diǎn)。當(dāng)?shù)貓D移動(dòng)時(shí),maker會(huì)做相應(yīng)的移動(dòng),maker移動(dòng)會(huì)帶動(dòng)shape移動(dòng)。所以,我們只管把shape內(nèi)部處理好就行了,不用管地圖移動(dòng)。maker的作用不大,并不能幫我們實(shí)現(xiàn)復(fù)雜的功能;Shape才是我們施展拳腳的地方。

2 用戶控件實(shí)現(xiàn)畫圖

在控件中UserControlFence實(shí)現(xiàn)電子圍欄的繪制,該控件會(huì)關(guān)聯(lián)到maker的shape。UserControlFence控件以Grid(name為gridRoot)布局;WPF的Path可以實(shí)現(xiàn)任意圖像的繪畫,首先要將Path加入到Grid。我們的輸入是多個(gè)gps點(diǎn)坐標(biāo),怎么能轉(zhuǎn)換成Path上各個(gè)點(diǎn)坐標(biāo)? 這需要經(jīng)過多次轉(zhuǎn)換;

Point ToCtrlPoint(PointLatLng gpsPoint)
  {
   //轉(zhuǎn)換成GMap.NET控件坐標(biāo)
   GPoint ptOfMapCtrl = MapCtrl.FromLatLngToLocal(gpsPoint);

   //GMap.NET控件坐標(biāo)要轉(zhuǎn)換成 控件相對(duì)于直接父面板的坐標(biāo)
   Point ptToMapCtrl2 = new Point(ptOfMapCtrl.X, ptOfMapCtrl.Y);
   //轉(zhuǎn)成屏幕坐標(biāo)
   Point ptOfScreen = MapCtrl.PointToScreen(ptToMapCtrl2);
   //轉(zhuǎn)換成相對(duì)于gridRoot的坐標(biāo)
   Point ptOfParentPanel = gridRoot.PointFromScreen(ptOfScreen);

   return ptOfParentPanel;
  }

轉(zhuǎn)換過程就是:相對(duì)于Map控件坐標(biāo)-->屏幕坐標(biāo)-->相對(duì)于Grid的坐標(biāo)。因?yàn)镻ath是Grid的Child,最后的坐標(biāo)也是相對(duì)于Grid的坐標(biāo)。用該坐標(biāo)繪制Path,就是電子圍欄的區(qū)域;

Path的Data是Geometry,生成Geometry函數(shù)如下:

private PathGeometry CreatPath()
  {
   if (_listPoints.Count <= 1)
   {
    PathRouteLine.Data = null;
    return null;
   }

   List<Point> listPt = ListWndPoint;

   PathFigure pathFigure = new PathFigure();
   pathFigure.StartPoint = listPt[0]; //起始點(diǎn)
   pathFigure.IsClosed = true;

   for (int i = 1; i < listPt.Count; i++)
   {
    //加入線段
    LineSegment line = new LineSegment() { Point = listPt[i] };
    pathFigure.Segments.Add(line);
   }

   PathGeometry geometry = new PathGeometry();
   geometry.Figures.Add(pathFigure);
   return geometry;
  }

這樣就完成電子圍欄的區(qū)域繪制。還有一點(diǎn)要注意:當(dāng)?shù)貓D縮放時(shí),必須重新繪制。地圖縮放比例不同,繪制區(qū)域大小也會(huì)改變(形狀不會(huì)變)。只需要監(jiān)視地圖控件的事件 public event MapZoomChanged OnMapZoomChanged;就行。

出入電子圍欄區(qū)域判斷

該判斷邏輯有多種實(shí)現(xiàn)方法,下面逐一介紹;

1 利用WPF的輔助函數(shù) VisualTreeHelper.HitTest

 通過判斷gps點(diǎn)坐標(biāo)是否在控件內(nèi)來判斷。gps坐標(biāo)先要轉(zhuǎn)成控件點(diǎn)坐標(biāo)(轉(zhuǎn)換函數(shù)見前文)。函數(shù)實(shí)現(xiàn)比較簡(jiǎn)單;

private bool IsInFence(PointLatLng gpsPoint)
  {
   if (_listPoints.Count <= 2)
    return false;
   Point ptWnd = ToCtrlPoint(gpsPoint);

   HitTestResult result = VisualTreeHelper.HitTest(gridRoot, ptWnd);
   if (result == null || result.VisualHit==null)
    return false;

   bool hit = result.VisualHit == PathRouteLineInner;
   return hit;
  }

2 通過GraphicsPath、Region實(shí)現(xiàn)

 這是System.Drawing下的一組類,屬于微軟早期的類庫;該類的點(diǎn)坐標(biāo)還是float型,精度不高。對(duì)于gps坐標(biāo)我先做了放大處理,如果不做處理誤差會(huì)很大。

private bool IsInFence2(PointLatLng gpsPoint)
  {
   double rate = 100000; //由于float精度問題。對(duì)坐標(biāo)放大處理,否則誤差會(huì)很大。
   System.Drawing.Drawing2D.GraphicsPath pointPath = new System.Drawing.Drawing2D.GraphicsPath();
   System.Drawing.PointF[] points = _listPoints.Select(o => new System.Drawing.PointF((float)(o.Lng * rate), (float)(o.Lat * rate))).ToArray();
   pointPath.AddLines(points);
   pointPath.CloseFigure();
    
   System.Drawing.Region region = new System.Drawing.Region(pointPath);
   System.Drawing.PointF ptHit = new System.Drawing.PointF((float)(gpsPoint.Lng * rate), (float)(gpsPoint.Lat * rate));
   bool visible = region.IsVisible(ptHit);
   return visible;
  }

3 直接根據(jù)點(diǎn)坐標(biāo)計(jì)算

 理論上這種方式效率是最高的,并且不依賴界面控件。但是這種方法不是微軟提供的,準(zhǔn)確性還需要驗(yàn)證。下面的函數(shù)是從網(wǎng)上找的,我對(duì)此計(jì)算結(jié)果做了驗(yàn)證,與前兩種計(jì)算方法的結(jié)果一致的。

private bool IsInFence3(PointLatLng gpsPoint)
  {
   int count = _listPoints.Count;
   if (count < 3)
   {
    return false;
   }

   bool result = false;
   for (int i = 0, j = count-1; i < count; i++)
   {
    var p1 = _listPoints[i];
    var p2 = _listPoints[j];

    if (p1.Lat < gpsPoint.Lat && p2.Lat >= gpsPoint.Lat || p2.Lat < gpsPoint.Lat && p1.Lat >= gpsPoint.Lat)
    {
     if (p1.Lng + (gpsPoint.Lat - p1.Lat) / (p2.Lat - p1.Lat) * (p2.Lng - p1.Lng) < gpsPoint.Lng)
     {
      result = !result;
     }
    }
    j = i;
   }
   return result;
  }

后記

電子圍欄區(qū)域繪制方法與軌跡回放、測(cè)距等處理有類似之處;GMap.Net為我們做的工作并不多,關(guān)鍵是要掌握處理這一類問題的精髓,做到舉一反三,許多問題就會(huì)迎刃而解。

以上就是c# 基于GMap.NET實(shí)現(xiàn)電子圍欄功能(WPF版)的詳細(xì)內(nèi)容,更多關(guān)于c# GMap.NET實(shí)現(xiàn)電子圍欄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中把Datatable轉(zhuǎn)換為Json的5個(gè)代碼實(shí)例

    C#中把Datatable轉(zhuǎn)換為Json的5個(gè)代碼實(shí)例

    這篇文章主要介紹了C#中把Datatable轉(zhuǎn)換為Json的5個(gè)代碼實(shí)例,需要的朋友可以參考下
    2014-04-04
  • C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題

    最近在 Web 部署百度 AI 圖像識(shí)別 AipSdk.dll 封裝庫的時(shí)候,在調(diào)用OCR圖像識(shí)別 API 的時(shí)候,顯示為 “ 基礎(chǔ)連接已經(jīng)關(guān)閉: 接收時(shí)發(fā)生錯(cuò)誤,” ,并且運(yùn)行后直接崩潰,所以本文給大家介紹了C#解決訪問API顯示基礎(chǔ)連接已經(jīng)關(guān)閉的問題,需要的朋友可以參考下
    2024-12-12
  • c#之事件用法

    c#之事件用法

    這篇文章介紹了c#中事件的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • 一文探索C#中實(shí)現(xiàn)雙向鏈表的方法

    一文探索C#中實(shí)現(xiàn)雙向鏈表的方法

    這篇文章主要為大家詳細(xì)介紹了C#中的雙向鏈表的實(shí)現(xiàn),揭秘雙向鏈表內(nèi)實(shí)現(xiàn)諸多方法的那些事,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Unity色子的投擲和點(diǎn)數(shù)的獲得詳析

    Unity色子的投擲和點(diǎn)數(shù)的獲得詳析

    這篇文章主要給大家介紹了關(guān)于Unity色子的投擲和點(diǎn)數(shù)的獲得的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • c# 類型轉(zhuǎn)換

    c# 類型轉(zhuǎn)換

    CLR最重要的特性之一就是類型安全性。在運(yùn)行時(shí),CLR總是知道一個(gè)對(duì)象是什么類型。調(diào)用GetType方法可以返回類型
    2012-10-10
  • Unity實(shí)現(xiàn)俄羅斯方塊(三)

    Unity實(shí)現(xiàn)俄羅斯方塊(三)

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)俄羅斯方塊的第一部分代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • C#實(shí)現(xiàn)Bitmap類型與Byte[]類型相互轉(zhuǎn)化的示例詳解

    C#實(shí)現(xiàn)Bitmap類型與Byte[]類型相互轉(zhuǎn)化的示例詳解

    在C#編程中,Bitmap類型和Byte[]類型之間的相互轉(zhuǎn)化是圖像處理和數(shù)據(jù)傳輸中常見的需求,Bitmap類型表示一個(gè)位圖圖像,而Byte[]類型則是一個(gè)字節(jié)數(shù)組,本文將詳細(xì)介紹如何在這兩種類型之間進(jìn)行相互轉(zhuǎn)化,需要的朋友可以參考下
    2024-07-07
  • C#?Winform消息通知之系統(tǒng)本地通知local?toast?notification

    C#?Winform消息通知之系統(tǒng)本地通知local?toast?notification

    這篇文章主要為大家介紹了C#?Winform消息通知之系統(tǒng)本地通知local?toast?notification使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • c#如何實(shí)現(xiàn)程序加密隱藏

    c#如何實(shí)現(xiàn)程序加密隱藏

    LiteDB是一個(gè)輕量級(jí)的嵌入式數(shù)據(jù)庫,它是用C#編寫的,適用于.NET平臺(tái),這篇文章主要介紹了如何通過LiteDB將自己的程序進(jìn)行加密,感興趣的可以了解下
    2023-08-08

最新評(píng)論

瑞昌市| 方城县| 青阳县| 铜川市| 重庆市| 宁化县| 石棉县| 仙游县| 甘肃省| 宜良县| 集安市| 禄劝| 贵定县| 德令哈市| 扶余县| 长丰县| 阿拉善盟| 滨州市| 凤山县| 庆城县| 德兴市| 深圳市| 昭苏县| 兴海县| 上思县| 新邵县| 平塘县| 南城县| 台湾省| 珠海市| 卢氏县| 延长县| 武宣县| 盐亭县| 新兴县| 嘉荫县| 巴南区| 攀枝花市| 义乌市| 正安县| 揭西县|