//________________________________________________________________________ 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)); } } } }