Пример #1
0
        /// <summary>
        /// </summary>
        /// <param name="startSpan"></param>
        /// <param name="borderDirection"></param>
        /// <param name="newRegionID"></param>
        private void partialFloodRegion(OpenHeightSpan startSpan,
                                        int borderDirection,
                                        int newRegionID)
        {
            int antiBorderDirection = NMGenUtility.AntiDir(borderDirection);
            int regionID            = startSpan.regionID();

            startSpan.setRegionID(newRegionID);
            startSpan.setDistanceToRegionCore(0);  //???所以这个值 没啥卵用啊,一直都是0的
            mwOpenSpans.Push(startSpan);
            mwBorderDistance.Push(0);

            while (mwOpenSpans.Count > 0)
            {
                OpenHeightSpan span     = mwOpenSpans.Pop();
                int            distance = mwBorderDistance.Pop();

                for (int i = 0; i < 4; ++i)
                {
                    OpenHeightSpan nSpan = span.getNeighbor(i);
                    if (null == nSpan ||
                        nSpan.regionID() != regionID)
                    {
                        continue;
                    }

                    int nDistance = distance;
                    if (i == borderDirection)   //null region所在的方向
                    {
                        //这里是不是应该小于等于0呢?
                        // 以这个距离Border为0作为边界,将大于0那一侧的Span全部变成
                        // 新的Region。然后小于等于0那一侧的作为旧的Region保留下来。
                        if (0 == distance)
                        {
                            continue;
                        }
                        nDistance--;
                    }
                    else if (i == antiBorderDirection)
                    {
                        nDistance++;
                    }

                    //注意上面的if-else,如果都不是这两个方向的Span
                    //会直接被重新设置为新的Region


                    nSpan.setRegionID(newRegionID);
                    nSpan.setDistanceToRegionCore(0);

                    mwOpenSpans.Push(nSpan);
                    mwBorderDistance.Push(nDistance);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// 重新设置对应的Region,根据拐点的情况
        /// </summary>
        /// <param name="referenceSpan"></param>
        /// <param name="borderDirection"></param>
        /// <param name="cornerDirection"></param>
        /// <returns></returns>
        private int selectedRegionID(OpenHeightSpan referenceSpan,
                                     int borderDirection,
                                     int cornerDirection)
        {
            referenceSpan.getDetailedRegionMap(ref mwNeighborRegions, 0);

            /*
             * Initial example state:
             *
             * a - Known region.
             * x - Null region.
             * u - Unknown, not checked yet.
             *
             *     u u u
             *     u a x
             *     u a a
             */

            int antiBorderDirection = NMGenUtility.AntiDir(borderDirection);
            int antiCornerDirection = NMGenUtility.AntiDir(cornerDirection);
            int regionID            = mwNeighborRegions[antiBorderDirection];

            if (regionID == referenceSpan.regionID() ||
                NULL_REGION == regionID)
            {
                /*
                 * The region away from the border is either a null region
                 * or the same region.  So we keep the current region.
                 *
                 *     u u u      u u u
                 *     a a x  or  x a x  <-- Potentially bad, but stuck with it.
                 *     u a a      u a a
                 */
                return(referenceSpan.regionID());
            }

            int potentialRegion = regionID;

            regionID = mwNeighborRegions[antiCornerDirection];
            if (regionID == referenceSpan.regionID() ||
                NULL_REGION == regionID)
            {
                /*
                 * The region opposite from the corner direction is
                 * either a null region or the same region.  So we
                 * keep the current region.
                 *
                 *     u a u      u x u
                 *     b a x  or  b a x
                 *     u a a      u a a
                 */
                return(referenceSpan.regionID());
            }

            int potentialCount = 0;
            int currentCount   = 0;

            for (int i = 0; i < 8; ++i)
            {
                if (mwNeighborRegions[i] == referenceSpan.regionID())
                {
                    currentCount++;
                }
                else if (mwNeighborRegions[i] == potentialRegion)
                {
                    potentialCount++;
                }
            }

            return(potentialCount < currentCount
                ? referenceSpan.regionID()
                : potentialRegion);
        }
Пример #3
0
        public void apply(OpenHeightfield field)
        {
            if (null == field)
            {
                Logger.LogError("[CLeanNullRegionBorders][apply]field null");
                return;
            }

            int nextRegionID = field.regionCount();

            OpenHeightfield.OpenHeightFieldIterator iter = field.GetEnumerator();
            while (iter.MoveNext())
            {
                OpenHeightSpan span = iter.Current;
                if (span.flags != 0)
                {
                    continue;
                }

                span.flags = 1;

                OpenHeightSpan workingSpan   = null;
                int            edgeDirection = -1;

                if (NULL_REGION == span.regionID())
                {
                    //找到Border Span第一个非空的邻居
                    edgeDirection = getNonNullBorderDrection(span);
                    if (-1 == edgeDirection)
                    {
                        continue;
                    }

                    //起点Span为有所属Region的Span
                    //而行走方向为 null Region所在的方向
                    workingSpan = span.getNeighbor(edgeDirection);
                    //转180度
                    edgeDirection = NMGenUtility.AntiDir(edgeDirection);
                }
                else if (!mUseOnlyNullSpans)
                {
                    //起点Span为 null Region的Span
                    //而行走方向即为有所属 Region 的 Span

                    edgeDirection = getNullBorderDrection(span);
                    if (-1 == edgeDirection)
                    {
                        continue;
                    }
                    workingSpan = span;
                }
                else
                {
                    continue;
                }

                //上面两个分支都会保证workingSpan是有所属Region的
                //而Dir 即是 Region 为 Null Region的Dir
                bool isEncompassedNullRegion = processNullRegion(workingSpan, edgeDirection);
                if (isEncompassedNullRegion)   //确定以这个Span为起点的Region,是一个单一Region,并且内含了一个Null Region
                {
                    //如果是完全包含了不可走的NullRegion ,就将这个Region分割成两个Region
                    partialFloodRegion(workingSpan, edgeDirection, nextRegionID);
                    nextRegionID++;
                }
            }

            field.setRegionCount(nextRegionID);

            iter.Reset();
            while (iter.MoveNext())
            {
                iter.Current.flags = 0;
            }
        }