Search code examples
mathgeometrygisrastertrigonometry

What is the average distance in crossing a raster 10x10 cell (square) assuming the path crosses the center point of the cell?


I have created a cost distance raster (a grid) of cell that are marked by their estimated travel time to cross the 10 meter cells. This is working under the assumption the path across the cells are perpendicular to the sides of the cell, which would be 10m in this case.

enter image description here

In trying to make this process more robust, I am trying to calculate the average time it takes to cross a square assuming an equal distribution of angles between 0 and 45 degrees.

enter image description here

I am trying to calculate the average distance to cross this 10 x 10 m square. I know its somewhere between 10m and 10√2. But I am not exactly sure how to settle the number. Do I simply average those two values out? I.E.

(10 + 10√2)/2 = 12.0710678


Solution

  • If the path crosses the center of the square, its length is 10/cos(θ), for θ from -π/4 to +π/4, where θ is the angle between the the path and the horizontal axis.

    Assuming, as you state, that all angles are equally probable (uniform distribution), the average is:

    1/(π/2) * integral(10/cos(θ), θ=-π/4..π/4) = 11.221997
    

    (wolfram alpha)

    For reasons of symmetry, the result is the same if you take only half of the angle interval:

    1/(π/4) * integral(10/cos(θ), θ=0..π/4) = 11.221997
    

    (wolfram alpha)

    The same for θ = -π/2 .. π/2, although for top-bottom paths (θ=-π/2..-π/4 and θ=π/4..π/2) the length is 10/|sin(θ)|:

    1/π * (integral(-10/sin(θ), θ=-π/2..-π/4) + integral(10/cos(θ), θ=-π/4..π/4) + integral(10/sin(θ), θ=π/4..π/2)) = 11.221997
    

    (wolfram alpha)

    Here's a basic Monte Carlo simulation with visuals

    const canvas = document.querySelector("canvas");
    const xA = 10, yA = 10, w = 200, h = w, y0 = xA + h/2;
    const ctx = canvas.getContext("2d");
    
    function line(theta, draw){
        const xLeft = xA, yLeft = y0 - w/2 * Math.tan(theta),
            xRight = xA + w, yRight = y0 + w/2 * Math.tan(theta);
        if(draw){
            ctx.beginPath();
            ctx.moveTo(xLeft, yLeft);
            ctx.lineTo(xRight, yRight);
            ctx.closePath();
            ctx.stroke();
        }
        return Math.sqrt((xRight-xLeft)**2 + (yRight-yLeft)**2);
    }
    
    ctx.strokeStyle = '#584';
    ctx.strokeRect(xA, yA, w, h);
    ctx.strokeStyle = '#f64';
    
    let sum = 0, n = 10000;
    for(let i = 0; i < n; i++){
        const theta = Math.random() * Math.PI/4;
        sum += line(theta, i % 100 === 0); // only draw a line once in 100 calculations
    }
    console.log('average length (for square of side 10) =', (sum/n/h*10)); // scaled back from h to 10
    <div>
        <canvas height="320" width="320" id="canvas"></canvas>
    </div>