/* 参考 :http://www.cnblogs.com/wantnon/p/4947067.html 
        *       http://fab.cba.mit.edu/classes/S62.12/docs/Meijster_distance.pdf
        * 具体算法名:Saito算法
        * 因为初始化值都是未知的,通过一个大约估计的初始化,来重复来回算一个大致准确的距离
        * 值 ?
        */
        public void generateDistanceField(OpenHeightfield field)
        {
            if (field == null)
            {
                Logger.LogError("[OpenHeightfieldBuilder][generateNeighborLinks]field Empty");
                return;
            }

          

            /*
             * 先将OpenHeightField的Span数据转换成0和1的二值图。如果是边缘Span
             * 那么就是0,否则就是NEEDS_INIT。
             */


            OpenHeightfield.OpenHeightFieldIterator iter = field.GetEnumerator(); 
            while( iter.MoveNext() )
            {
                OpenHeightSpan span = iter.Current;
                bool isBorder = false; 

                for(int dir = 0; dir < 4; ++dir)
                {
                    OpenHeightSpan nSpan = span.getNeighbor(dir); 
                    if( null == nSpan
                        || nSpan.getNeighbor(dir == 3 ? 0 : dir + 1) == null) 
                    {
                        //如果8个邻居有任何一个缺失的话,那么就是边界Border
                        isBorder = true;
                        break;
                    }
                }

                if( isBorder )
                {
                    //自己就是边界Border
                    span.setDistanceToBorder(BORDER); 
                }
                else
                {
                    //需要再次计算
                    span.setDistanceToBorder(NEEDS_INIT);
                }
            } //while


            /*
             * 逆时针访问?
             *     
             *    (-1,1)  (0,1)  (1,1)
             *    (-1,0)    x    (1,0)
             *    (-1,-1) (0,-1) (1,-1)
             */

            //Pass 1
            //顺序访问 (-1,0) (-1,-1) (0,-1) (1,-1)
            iter.Reset(); 
            while( iter.MoveNext() )
            {
                OpenHeightSpan span = iter.Current;
                int selfDist = span.distanceToBorder(); 

                if( selfDist == BORDER)
                {
                    continue; 
                }

                //(-1,0)
                OpenHeightSpan nSpan = span.getNeighbor(0);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, true);

                //(-1,-1),左下角的领域
                nSpan = nSpan.getNeighbor(3); //领域0的领域3,也就是原Span的左下角
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, false);

                //(0,-1)
                nSpan = span.getNeighbor(3);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, true);

                //(1,-1) 
                nSpan = nSpan.getNeighbor(2);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, true);
                
                span.setDistanceToBorder(selfDist); 

            } // while


            //Pass 2
            //顺序访问 (1,0) (1,1) (0,1) (-1,1)
            //注意这个是反向遍历
            iter.ReverseReset(); 
            while( iter.MoveNext() )
            {
                OpenHeightSpan span = iter.Current;
                int selfDist = span.distanceToBorder();
                if( selfDist == BORDER )
                {
                    continue; 
                }

                /* 
                 * 因为经过Pass1之后 ,所有的Span要么就是Border
                 * 要么就是有个大概值的,不会等于NEED_INIT的。
                 * 所以直接按照按照上面的流程跑
                 */

                //(1,0)
                OpenHeightSpan nSpan = span.getNeighbor(2);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, true);

                //(1,1)
                nSpan = nSpan.getNeighbor(1);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, false);

                //(0,1)
                nSpan = span.getNeighbor(1);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, true);

                //(-1,1)
                nSpan = nSpan.getNeighbor(0);
                selfDist = calcMiniDistanceToBorder(selfDist, nSpan, false);

                span.setDistanceToBorder(selfDist); 
            }

            field.clearBorderDistanceBounds(); 
        }