ScopeLimit.cs 4.9 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace DeviceLibrary
{
    public class ScopeLimit
    {
        List<string> agvIPs;
        //不规则图像坐标
        List<Agv_Info.AgvPosition> positions;
        Thread threadPoll;//监控线程
        /// <summary>
        /// 区域是否可用
        /// </summary>
        public bool Available { get; private set; } = true;
        public delegate void ScopeLimitStateChangedEventHandler(string ip, bool state);
        public event ScopeLimitStateChangedEventHandler ScopeLimitStateChangedEvent;
        public ScopeLimit(List<Agv_Info.AgvPosition> positions)
        {
            agvIPs = new List<string>();
            agvIPs.AddRange(new string[]
            {
                "10.85.199.68",
                "10.85.199.69",
                "10.85.199.70",
                "10.85.199.71",
                "10.85.199.72",
                "10.85.199.73",
                "10.85.199.74",
                "10.85.199.80",
                "10.85.199.81",
                "10.85.199.114"
            });
            this.positions = positions;
            //threadPoll = new Thread(ScopeDetecting);
            //threadPoll.IsBackground = true;
            //threadPoll.Start();
        }
        private void ScopeDetecting()
        {
            bool rtn;
            while (true)
            {
                Thread.Sleep(5000);
                List<string> agvs = new List<string>();
                foreach (string ip in agvIPs)
                {
                    Thread.Sleep(1000);
                    rtn = MiR_API.Get_Position(ip, CommonVar.agvInfo[0].Authorization, out Agv_Info.AgvPosition position);
                    if (rtn)
                    {
                        if (IsInPolygon(position, positions))
                        {
                            agvs.Add(ip);
                        }
                    }
                }
                if (agvs.Count > 0)
                {
                    Available = false;
                    ScopeLimitStateChangedEvent?.Invoke(string.Join(";", agvs), Available);
                }
                else //不在限制区域
                {
                    if (!Available)
                    {
                        Available = true;
                        ScopeLimitStateChangedEvent?.Invoke("", Available);
                    }
                }
            }
        }

        /// <summary>  
        /// 判断点是否在多边形内.  
        /// ----------原理----------  
        /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,  
        /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。  
        /// </summary>  
        /// <param name="checkPoint">要判断的点</param>  
        /// <param name="polygonPoints">多边形的顶点</param>  
        /// <returns></returns>  
        bool IsInPolygon(Agv_Info.AgvPosition checkPoint, List<Agv_Info.AgvPosition> polygonPoints)
        {
            bool inside = false;
            int pointCount = polygonPoints.Count;
            Agv_Info.AgvPosition p1, p2;
            for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点...  
            {
                p1 = polygonPoints[i];
                p2 = polygonPoints[j];
                if (checkPoint.y < p2.y)
                {//p2在射线之上  
                    if (p1.y <= checkPoint.y)
                    {//p1正好在射线中或者射线下方  
                        if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧  
                        {
                            //射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。  
                            //由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside)  
                            //所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside)  
                            inside = (!inside);
                        }
                    }
                }
                else if (checkPoint.y < p1.y)
                {
                    //p2正好在射线中或者在射线下方,p1在射线上  
                    if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧  
                    {
                        inside = (!inside);
                    }
                }
            }
            return inside;
        }
    }
}