public Result<FindRandomPointResult> findRandomPoint(QueryFilter filter, FRand frand) {
        // Randomly pick one tile. Assume that all tiles cover roughly the same area.
        if (Objects.isNull(filter) || Objects.isNull(frand)) {
            return Result.invalidParam();
        }
        MeshTile tile = null;
        float tsum = 0.0f;
        for (int i = 0; i < m_nav.getMaxTiles(); i++) {
            MeshTile t = m_nav.getTile(i);
            if (t == null || t.data == null || t.data.header == null) {
                continue;
            }

            // Choose random tile using reservoi sampling.
            float area = 1.0f; // Could be tile area too.
            tsum += area;
            float u = frand.frand();
            if (u * tsum <= area) {
                tile = t;
            }
        }
        if (tile == null) {
            return Result.invalidParam("Tile not found");
        }

        // Randomly pick one polygon weighted by polygon area.
        Poly poly = null;
        long polyRef = 0;
        long base = m_nav.getPolyRefBase(tile);

        float areaSum = 0.0f;
        for (int i = 0; i < tile.data.header.polyCount; ++i) {
            Poly p = tile.data.polys[i];
            // Do not return off-mesh connection polygons.
            if (p.getType() != Poly.DT_POLYTYPE_GROUND) {
                continue;
            }
            // Must pass filter
            long ref = base | i;
            if (!filter.passFilter(ref, tile, p)) {
                continue;
            }

            // Calc area of the polygon.
            float polyArea = 0.0f;
            for (int j = 2; j < p.vertCount; ++j) {
                int va = p.verts[0] * 3;
                int vb = p.verts[j - 1] * 3;
                int vc = p.verts[j] * 3;
                polyArea += triArea2D(tile.data.verts, va, vb, vc);
            }

            // Choose random polygon weighted by area, using reservoi sampling.
            areaSum += polyArea;
            float u = frand.frand();
            if (u * areaSum <= polyArea) {
                poly = p;
                polyRef = ref;
            }
        }

        if (poly == null) {
            return Result.invalidParam("Poly not found");
        }

        // Randomly pick point on polygon.
        float[] verts = new float[3 * m_nav.getMaxVertsPerPoly()];
        float[] areas = new float[m_nav.getMaxVertsPerPoly()];
        System.arraycopy(tile.data.verts, poly.verts[0] * 3, verts, 0, 3);
        for (int j = 1; j < poly.vertCount; ++j) {
            System.arraycopy(tile.data.verts, poly.verts[j] * 3, verts, j * 3, 3);
        }

        float s = frand.frand();
        float t = frand.frand();

        float[] pt = randomPointInConvexPoly(verts, poly.vertCount, areas, s, t);
        FindRandomPointResult result = new FindRandomPointResult(polyRef, pt);
        Result<Float> pheight = getPolyHeight(polyRef, pt);
        if (pheight.failed()) {
            return Result.of(pheight.status, result);
        }
        pt[1] = pheight.result;
        return Result.success(result);
    }
public Result < FindRandomPointResult > findRandomPoint ( QueryFilter filter , FRand frand ) { if ( Objects . isNull ( filter ) || Objects . isNull ( frand ) ) { return Result . invalidParam ( ) ; } MeshTile tile = null ; float tsum = 0.0f ; for ( int i = 0 ; i < m_nav . getMaxTiles ( ) ; i ++ ) { MeshTile t = m_nav . getTile ( i ) ; if ( t == null || t . data == null || t . data . header == null ) { continue ; } float area = 1.0f ; tsum += area ; float u = frand . frand ( ) ; if ( u * tsum <= area ) { tile = t ; } } if ( tile == null ) { return Result . invalidParam ( "Tile not found" ) ; } Poly poly = null ; long polyRef = 0 ; long base = m_nav . getPolyRefBase ( tile ) ; float areaSum = 0.0f ; for ( int i = 0 ; i < tile . data . header . polyCount ; ++ i ) { Poly p = tile . data . polys [ i ] ; if ( p . getType ( ) != Poly . DT_POLYTYPE_GROUND ) { continue ; } long ref = base | i ; if ( ! filter . passFilter ( ref , tile , p ) ) { continue ; } float polyArea = 0.0f ; for ( int j = 2 ; j < p . vertCount ; ++ j ) { int va = p . verts [ 0 ] * 3 ; int vb = p . verts [ j - 1 ] * 3 ; int vc = p . verts [ j ] * 3 ; polyArea += triArea2D ( tile . data . verts , va , vb , vc ) ; } areaSum += polyArea ; float u = frand . frand ( ) ; if ( u * areaSum <= polyArea ) { poly = p ; polyRef = ref ; } } if ( poly == null ) { return Result . invalidParam ( "Poly not found" ) ; } float [ ] verts = new float [ 3 * m_nav . getMaxVertsPerPoly ( ) ] ; float [ ] areas = new float [ m_nav . getMaxVertsPerPoly ( ) ] ; System . arraycopy ( tile . data . verts , poly . verts [ 0 ] * 3 , verts , 0 , 3 ) ; for ( int j = 1 ; j < poly . vertCount ; ++ j ) { System . arraycopy ( tile . data . verts , poly . verts [ j ] * 3 , verts , j * 3 , 3 ) ; } float s = frand . frand ( ) ; float t = frand . frand ( ) ; float [ ] pt = randomPointInConvexPoly ( verts , poly . vertCount , areas , s , t ) ; FindRandomPointResult result = new FindRandomPointResult ( polyRef , pt ) ; Result < Float > pheight = getPolyHeight ( polyRef , pt ) ; if ( pheight . failed ( ) ) { return Result . of ( pheight . status , result ) ; } pt [ 1 ] = pheight . result ; return Result . success ( result ) ; }
Returns random location on navmesh. Polygons are chosen weighted by area. The search runs in linear related to
number of polygon.

@param filter
The polygon filter to apply to the query.
@param frand
Function returning a random number [0..1).
@return Random location