點在多邊形內演算法,C#判斷一個點是否在一個複雜多邊形的內部

來源:互聯網
上載者:User

標籤:ase   main   實現   void   osi   param   rtx   ret   分享   

判斷一點是否在不規則映像的內部演算法,如是由一個個點組成的不規則映像,判斷某一點是否在不規則矩形內部,先上

演算法實現如下,演算法簡單,親試有效

 

    public class PositionAlgorithmHelper    {        /// <summary>        /// 判斷當前位置是否在不規則形狀裡面        /// </summary>        /// <param name="nvert">不規則形狀的定點數</param>        /// <param name="vertx">當前x座標</param>        /// <param name="verty">當前y座標</param>        /// <param name="testx">不規則形狀x座標集合</param>        /// <param name="testy">不規則形狀y座標集合</param>        /// <returns></returns>        public static bool PositionPnpoly(int nvert, List<double> vertx, List<double> verty, double testx, double testy)        {            int i, j, c = 0;            for (i = 0, j = nvert - 1; i < nvert; j = i++)            {                if (((verty[i] > testy) != (verty[j] > testy)) && (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))                {                    c = 1 + c; ;                }            }            if (c % 2 == 0)            {                return false;            }            else            {                return true;            }        }    }

用座標進行測試:

    class Program    {        static void Main(string[] args)        {            test1();        }        /// <summary>        /// test1        /// </summary>        public static void test1()        {            //不規則映像座標            List<Position> position = new List<Position>();            position.Add(new Position() { x = 6, y = 0 });            position.Add(new Position() { x = 10, y = 2 });            position.Add(new Position() { x = 16, y = 2 });            position.Add(new Position() { x = 20, y = 6 });            position.Add(new Position() { x = 14, y = 10 });            position.Add(new Position() { x = 16, y = 6 });            position.Add(new Position() { x = 12, y = 6 });            position.Add(new Position() { x = 14, y = 8 });            position.Add(new Position() { x = 10, y = 8 });            position.Add(new Position() { x = 8, y = 6 });            position.Add(new Position() { x = 12, y = 4 });            position.Add(new Position() { x = 6, y = 4 });            position.Add(new Position() { x = 8, y = 2 });            //使用者當前位置座標            List<Position> userPositions = new List<Position>();            userPositions.Add(new Position() { x = 14, y = 4 });            userPositions.Add(new Position() { x = 15, y = 4 });            userPositions.Add(new Position() { x = 10, y = 6 });            userPositions.Add(new Position() { x = 8, y = 5 });            //不規則映像x座標集合            List<double> xList = position.Select(x => x.x).ToList();            //不規則映像y座標集合            List<double> yList = position.Select(x => x.y).ToList();            foreach (var userPosition in userPositions)            {                bool result = PositionAlgorithmHelper.PositionPnpoly(position.Count, xList, yList, userPosition.x, userPosition.y);                if (result)                {                    Console.WriteLine(string.Format("{0},{1}【在】座標內", userPosition.x, userPosition.y));                }                else                {                    Console.WriteLine(string.Format("{0},{1}【不在】座標內", userPosition.x, userPosition.y));                }            }        }    }

另外兩種方式:

        /// <summary>          /// 判斷點是否在多邊形內.          /// ----------原理----------          /// 注意到如果從P作水平向左的射線的話,如果P在多邊形內部,那麼這條射線與多邊形的交點必為奇數,          /// 如果P在多邊形外部,則交點個數必為偶數(0也在內)。          /// 所以,我們可以順序考慮多邊形的每條邊,求出交點的總個數。還有一些特殊情況要考慮。假如考慮邊(P1,P2),          /// 1)如果射線正好穿過P1或者P2,那麼這個交點會被算作2次,處理辦法是如果P的從座標與P1,P2中較小的縱座標相同,則直接忽略這種情況          /// 2)如果射線水平,則射線要麼與其無交點,要麼有無數個,這種情況也直接忽略。          /// 3)如果射線豎直,而P0的橫座標小於P1,P2的橫座標,則必然相交。          /// 4)再判斷相交之前,先判斷P是否在邊(P1,P2)的上面,如果在,則直接得出結論:P再多邊形內部。          /// </summary>          /// <param name="checkPoint">要判斷的點</param>          /// <param name="polygonPoints">多邊形的頂點</param>          /// <returns></returns>          public static bool IsInPolygon2(Position checkPoint, List<Position> polygonPoints)        {            int counter = 0;            int i;            double xinters;            Position p1, p2;            int pointCount = polygonPoints.Count;            p1 = polygonPoints[0];            for (i = 1; i <= pointCount; i++)            {                p2 = polygonPoints[i % pointCount];                if (checkPoint.y > Math.Min(p1.y, p2.y)//校正點的Y大於線段端點的最小Y                      && checkPoint.y <= Math.Max(p1.y, p2.y))//校正點的Y小於線段端點的最大Y                  {                    if (checkPoint.x <= Math.Max(p1.x, p2.x))//校正點的X小於等線段端點的最大X(使用校正點的左射線判斷).                      {                        if (p1.y != p2.y)//線段不平行於X軸                          {                            xinters = (checkPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;                            if (p1.x == p2.x || checkPoint.x <= xinters)                            {                                counter++;                            }                        }                    }                }                p1 = p2;            }            if (counter % 2 == 0)            {                return false;            }            else            {                return true;            }        }        /// <summary>          /// 判斷點是否在多邊形內.          /// ----------原理----------          /// 注意到如果從P作水平向左的射線的話,如果P在多邊形內部,那麼這條射線與多邊形的交點必為奇數,          /// 如果P在多邊形外部,則交點個數必為偶數(0也在內)。          /// </summary>          /// <param name="checkPoint">要判斷的點</param>          /// <param name="polygonPoints">多邊形的頂點</param>          /// <returns></returns>          public static bool IsInPolygon(Position checkPoint, List<Position> polygonPoints)        {            bool inside = false;            int pointCount = polygonPoints.Count;            Position 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;        }  

 

點在多邊形內演算法,C#判斷一個點是否在一個複雜多邊形的內部

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.