public static void filterLedgeSpans(Context ctx, int walkableHeight, int walkableClimb, Heightfield solid) {
        ctx.startTimer("FILTER_BORDER");

        int w = solid.width;
        int h = solid.height;
        int MAX_HEIGHT = 0xffff;

        // Mark border spans.
        for (int y = 0; y < h; ++y) {
            for (int x = 0; x < w; ++x) {
                for (Span s = solid.spans[x + y * w]; s != null; s = s.next) {
                    // Skip non walkable spans.
                    if (s.area == RecastConstants.RC_NULL_AREA)
                        continue;

                    int bot = (s.smax);
                    int top = s.next != null ? s.next.smin : MAX_HEIGHT;

                    // Find neighbours minimum height.
                    int minh = MAX_HEIGHT;

                    // Min and max height of accessible neighbours.
                    int asmin = s.smax;
                    int asmax = s.smax;

                    for (int dir = 0; dir < 4; ++dir) {
                        int dx = x + RecastCommon.GetDirOffsetX(dir);
                        int dy = y + RecastCommon.GetDirOffsetY(dir);
                        // Skip neighbours which are out of bounds.
                        if (dx < 0 || dy < 0 || dx >= w || dy >= h) {
                            minh = Math.min(minh, -walkableClimb - bot);
                            continue;
                        }

                        // From minus infinity to the first span.
                        Span ns = solid.spans[dx + dy * w];
                        int nbot = -walkableClimb;
                        int ntop = ns != null ? ns.smin : MAX_HEIGHT;
                        // Skip neightbour if the gap between the spans is too small.
                        if (Math.min(top, ntop) - Math.max(bot, nbot) > walkableHeight)
                            minh = Math.min(minh, nbot - bot);

                        // Rest of the spans.
                        for (ns = solid.spans[dx + dy * w]; ns != null; ns = ns.next) {
                            nbot = ns.smax;
                            ntop = ns.next != null ? ns.next.smin : MAX_HEIGHT;
                            // Skip neightbour if the gap between the spans is too small.
                            if (Math.min(top, ntop) - Math.max(bot, nbot) > walkableHeight) {
                                minh = Math.min(minh, nbot - bot);

                                // Find min/max accessible neighbour height.
                                if (Math.abs(nbot - bot) <= walkableClimb) {
                                    if (nbot < asmin)
                                        asmin = nbot;
                                    if (nbot > asmax)
                                        asmax = nbot;
                                }

                            }
                        }
                    }

                    // The current span is close to a ledge if the drop to any
                    // neighbour span is less than the walkableClimb.
                    if (minh < -walkableClimb)
                        s.area = RecastConstants.RC_NULL_AREA;

                    // If the difference between all neighbours is too large,
                    // we are at steep slope, mark the span as ledge.
                    if ((asmax - asmin) > walkableClimb) {
                        s.area = RecastConstants.RC_NULL_AREA;
                    }
                }
            }
        }

        ctx.stopTimer("FILTER_BORDER");
    }
public static void filterLedgeSpans ( Context ctx , int walkableHeight , int walkableClimb , Heightfield solid ) { ctx . startTimer ( "FILTER_BORDER" ) ; int w = solid . width ; int h = solid . height ; int MAX_HEIGHT = 0xffff ; for ( int y = 0 ; y < h ; ++ y ) { for ( int x = 0 ; x < w ; ++ x ) { for ( Span s = solid . spans [ x + y * w ] ; s != null ; s = s . next ) { if ( s . area == RecastConstants . RC_NULL_AREA ) continue ; int bot = ( s . smax ) ; int top = s . next != null ? s . next . smin : MAX_HEIGHT ; int minh = MAX_HEIGHT ; int asmin = s . smax ; int asmax = s . smax ; for ( int dir = 0 ; dir < 4 ; ++ dir ) { int dx = x + RecastCommon . GetDirOffsetX ( dir ) ; int dy = y + RecastCommon . GetDirOffsetY ( dir ) ; if ( dx < 0 || dy < 0 || dx >= w || dy >= h ) { minh = Math . min ( minh , - walkableClimb - bot ) ; continue ; } Span ns = solid . spans [ dx + dy * w ] ; int nbot = - walkableClimb ; int ntop = ns != null ? ns . smin : MAX_HEIGHT ; if ( Math . min ( top , ntop ) - Math . max ( bot , nbot ) > walkableHeight ) minh = Math . min ( minh , nbot - bot ) ; for ( ns = solid . spans [ dx + dy * w ] ; ns != null ; ns = ns . next ) { nbot = ns . smax ; ntop = ns . next != null ? ns . next . smin : MAX_HEIGHT ; if ( Math . min ( top , ntop ) - Math . max ( bot , nbot ) > walkableHeight ) { minh = Math . min ( minh , nbot - bot ) ; if ( Math . abs ( nbot - bot ) <= walkableClimb ) { if ( nbot < asmin ) asmin = nbot ; if ( nbot > asmax ) asmax = nbot ; } } } } if ( minh < - walkableClimb ) s . area = RecastConstants . RC_NULL_AREA ; if ( ( asmax - asmin ) > walkableClimb ) { s . area = RecastConstants . RC_NULL_AREA ; } } } } ctx . stopTimer ( "FILTER_BORDER" ) ; }
/ @see rcHeightfield, rcConfig