示例#1
0
        //________________________________________________________________________

        internal bool Fill(PointSpeedBuffer source)
        {
            if (source == null)
            {
                this.m_Count = 0;
                return(true);
            }

            int iCount = source.Count;

            if (iCount <= 0)
            {
                this.m_Count = 0;
                return(true);
            }

            if (iCount > this.m_Capacity)
            {
                return(false);
            }

            this.m_Count = iCount;
            System.Array.Copy(source.m_Buffer, 0, this.m_Buffer, 0, this.m_Count);
            return(true);
        }
        //________________________________________________________________________

        internal void SetAll(PointSpeedBuffer list, CellType value)
        {
            if (list == null)
            {
                return;
            }
            int index = list.Count;

            while (--index >= 0)
            {
                var pt = list.m_Buffer[index];
                this.m_Buffer[pt.Row, pt.Column] = value;
            }
        }
        //________________________________________________________________________

        private static int FindNextPoint(Matrix matrix, PointSpeedBuffer buffer, Point end, int index, bool first)
        {
            if ((index + 1) >= buffer.m_Capacity)
            {
                return(-1);
            }
            PointSide side  = PointSide.None;
            Point     point = buffer.m_Buffer[index];
            Point     back  = buffer.m_Buffer[index - 1];
            Point     next;

            //-----
            if (first)
            {
                //For speed.
                next = point; --next.Row; //Top
                if ((next != back) && (buffer.IndexOf(next) >= 0))
                {
                    return(-1);
                }
                if (next == end)
                {
                    buffer.m_Buffer[index + 1] = next;
                    return(+1);
                }

                next = point; ++next.Column; //Right
                if ((next != back) && (buffer.IndexOf(next) >= 0))
                {
                    return(-1);
                }
                if (next == end)
                {
                    buffer.m_Buffer[index + 1] = next;
                    return(+1);
                }

                next = point; ++next.Row; //Bottom
                if ((next != back) && (buffer.IndexOf(next) >= 0))
                {
                    return(-1);
                }
                if (next == end)
                {
                    buffer.m_Buffer[index + 1] = next;
                    return(+1);
                }

                next = point; --next.Column; //Left
                if ((next != back) && (buffer.IndexOf(next) >= 0))
                {
                    return(-1);
                }
                if (next == end)
                {
                    buffer.m_Buffer[index + 1] = next;
                    return(+1);
                }
            }
            else
            {
                next = buffer.m_Buffer[index + 1];

                if (point.Column == next.Column)
                {
                    if ((point.Row - 1) == next.Row)
                    {
                        side = PointSide.Top;
                    }
                    else if ((point.Row + 1) == next.Row)
                    {
                        side = PointSide.Bottom;
                    }
                }
                else if (point.Row == next.Row)
                {
                    if ((point.Column - 1) == next.Column)
                    {
                        side = PointSide.Left;
                    }
                    else if ((point.Column + 1) == next.Column)
                    {
                        side = PointSide.Right;
                    }
                }

#if (DEBUG)
                if (side == PointSide.None)
                {
                    System.Diagnostics.Debugger.Break();
                }
#endif
            }
            //-----Goto next point ...
            byte maxRow = (byte)(matrix.m_Size.Row - 2);
            byte maxCol = (byte)(matrix.m_Size.Column - 2);
            while (true)
            {
                ++side;
                next = point.GetSidePoint(side);
                if (next == point)
                {
                    return(-1);               //side != Top|Right|Bottom|Left
                }
                //-----Range test ...
                if ((next.Row <= 0) || (next.Column <= 0) || (next.Row > maxRow) || (next.Column > maxCol))
                {
                    continue;
                }

                //-----Is fix ...
                if (matrix.m_Buffer[next.Row, next.Column] == CellType.Verde)
                {
                    continue;
                }

                //-----Exist test ...
                if (next == back)
                {
                    continue;
                }

#if (DEBUG)
                if (buffer.IndexOf(next) >= 0)
                {
                    System.Diagnostics.Debugger.Break();
                }
#endif

                //----Next point finded ...
                buffer.m_Buffer[index + 1] = next;
                return(+1);
            }
        }
        //________________________________________________________________________

        private void AsyncStart(object state)
        {
            PointSpeedBuffer pathMin = null;

            long version = (long)state;

            try
            {
                if (this.m_Version != version)
                {
                    return;
                }

                //-----Validation ...
                if ((this.m_Matrix.m_Size.Row <= 2) || (this.m_Matrix.m_Size.Column <= 2))
                {
                    return;
                }

                //-----Find start and end point ...
                Point ptStart, ptEnd;
                Point ptStartInside, ptEndInside; //For speed.
                if (!FindInputAndOutputPoints(this.m_Matrix, out ptStart, out ptStartInside, out ptEnd, out ptEndInside))
                {
                    return;
                }

                //-----Initialize ....
                pathMin = new PointSpeedBuffer((this.m_Matrix.m_Size.Column - 2) * (this.m_Matrix.m_Size.Row - 2));

                if ((ptStart == ptEndInside) || (ptStartInside == ptEnd))
                {
                    pathMin.m_Buffer[pathMin.m_Count++] = ptStart;
                    pathMin.m_Buffer[pathMin.m_Count++] = ptEnd;
                    return;
                }

                var matrix = new Matrix(this.m_Matrix);
                matrix.ClearWay();

                //-----Remove close points. Only for speed and performance.
                RemoveClosePoints_Pass1(matrix);
                RemoveClosePoints_Pass2(matrix);

                if (
                    (matrix.m_Buffer[ptStartInside.Row, ptStartInside.Column] == CellType.Verde) ||
                    (matrix.m_Buffer[ptEndInside.Row, ptEndInside.Column] == CellType.Verde)
                    )
                {
                    pathMin = null;
                    return;
                }
                //-----
                var pathCur = new PointSpeedBuffer((this.m_Matrix.m_Size.Column - 2) * (this.m_Matrix.m_Size.Row - 2));

                pathMin.m_Count = int.MaxValue;
                pathCur.m_Buffer[pathCur.m_Count++] = ptStart;
                pathCur.m_Buffer[pathCur.m_Count++] = ptStartInside;

                //-----Start ....
                --pathCur.m_Count;
                int iFront = 1;
                while (true)
                {
                    if (this.m_Version != version)
                    {
                        return;
                    }

                    if (this.m_DebugMode)
                    {
                        this.OnResult(new ResultEventArgs(pathCur, false));
                        System.Threading.Thread.Sleep(SLEEPINDEBUGMODE);
                    }

                    if (iFront > 0)
                    {
                        ++pathCur.m_Count;
                    }
                    else
                    {
                        pathCur.m_Count += iFront;
                        if (pathCur.m_Count <= 1)
                        {
                            break;
                        }
                    }


                    iFront = FindNextPoint(matrix, pathCur, ptEndInside, pathCur.m_Count - 1, iFront > 0);
                    if (iFront > 0)
                    {
                        if (pathCur.m_Buffer[pathCur.m_Count] == ptEndInside) //Found a true path?
                        {
                            if (pathCur.m_Count < (pathCur.m_Capacity - 2))
                            {
                                ++pathCur.m_Count;
                                pathCur.m_Buffer[pathCur.m_Count++] = ptEnd;

                                if (pathCur.m_Count < pathMin.m_Count)
                                {
                                    pathMin.Fill(pathCur);
                                    this.OnResult(new ResultEventArgs(pathMin, false));
                                }

                                if (pathCur.m_Count <= 5)
                                {
                                    break;
                                }
                                iFront = -3;
                            }
                            else
                            {
                                iFront = -1;
                            }
                        }
                        else
                        {
                            iFront = +1;
                        }
                    }
                    else if (pathCur.m_Count <= 2)
                    {
                        break;
                    }
                }
            }
            catch
            {
                if (System.Threading.Interlocked.Read(ref this.m_Version) != version)
                {
                    return;
                }
                pathMin = null;
#if (DEBUG)
                System.Diagnostics.Debugger.Break();
#endif
            }
            finally
            {
                if (System.Threading.Interlocked.Read(ref this.m_Version) == version)
                {
                    if ((pathMin == null) || (pathMin.m_Count <= 1) || (pathMin.m_Count > pathMin.m_Capacity))
                    {
                        //-----Not found ...
                        this.OnResult(new ResultEventArgs(null, true));
                    }
                    else
                    {
                        //-----Found ...
                        this.OnResult(new ResultEventArgs(pathMin, true));
                    }
                }
            }
        }