How do I calculate total down slope distances

import math

nwC    ={ 
1:  {"E": 314650, "N": 424575, "RL": 1805.5},
          2:  {"E": 314525, "N": 424475, "RL": 1820.5},
          3:  {"E": 314400, "N": 424375, "RL": 1835.5},
          4:  {"E": 314500, "N": 424550, "RL": 1850.5},
          5:  {"E": 314550, "N": 424650, "RL": 1865.5}, 
          6:  {"E": 314625, "N": 424750, "RL": 1880.5},
          7:  {"E": 314700, "N": 424850, "RL": 1895.5},
          8:  {"E": 314725, "N": 424975, "RL": 1910.5},
          9:  {"E": 314700, "N": 425125, "RL": 1925.5},
          10: {"E": 314675, "N": 425250, "RL": 1940.5},
          11: {"E": 314625, "N": 425300, "RL": 1955.5},
          12: {"E": 314600, "N": 425100, "RL": 1970.5},
          13: {"E": 314600, "N": 424975, "RL": 1985.5},
          14: {"E": 314500, "N": 424800, "RL": 2000.5},
          15: {"E": 314400, "N": 424775, "RL": 2015.5},
          16: {"E": 314300, "N": 424725, "RL": 2030.5},
          17: {"E": 314225, "N": 424600, "RL": 2045.5},
          18: {"E": 314100, "N": 424600, "RL": 2060.5},
          19: {"E": 313975, "N": 424575, "RL": 2075.5},
          20: {"E": 313875, "N": 424525, "RL": 2090.5}}

def rampTotalDistance(dictName, start_index, end_index):
    total_down = 0
    for i in range(start_index, end_index + 1):  # Include end_index
        if i < end_index:  # Prevent index out of range error
            # Ramp down slope distance.
            if dictName[i + 1]["RL"] > dictName[i]["RL"]:
                ramp_down_distance = math.sqrt(
                    (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
                    (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
                    (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)
                              
                total_down += ramp_down_distance
        return total_down
    
dist = rampTotalDistance(nwC,1,20)                 

print(f"Total down distance: {dist}")

The main problen is that the return is indented inside the loop. You want it at the same level as the main body of the loop, that is to say, the same level as total_down = 0 and for .

But also, you do not need to include end_index in the values of i. Just use range(start_index, end_index + 1). It does not prevent you referring to i+1 in your calculation. So you don’t need the first if.

import math

nwC    ={ 1:  {"E": 314650, "N": 424575, "RL": 1805.5},
          2:  {"E": 314525, "N": 424475, "RL": 1820.5},
          3:  {"E": 314400, "N": 424375, "RL": 1835.5},
          4:  {"E": 314500, "N": 424550, "RL": 1850.5},
          5:  {"E": 314550, "N": 424650, "RL": 1865.5}, 
          6:  {"E": 314625, "N": 424750, "RL": 1880.5},
          7:  {"E": 314700, "N": 424850, "RL": 1895.5},
          8:  {"E": 314725, "N": 424975, "RL": 1910.5},
          9:  {"E": 314700, "N": 425125, "RL": 1925.5},
          10: {"E": 314675, "N": 425250, "RL": 1940.5},
          11: {"E": 314625, "N": 425300, "RL": 1955.5},
          12: {"E": 314600, "N": 425100, "RL": 1970.5},
          13: {"E": 314600, "N": 424975, "RL": 1985.5},
          14: {"E": 314500, "N": 424800, "RL": 2000.5},
          15: {"E": 314400, "N": 424775, "RL": 2015.5},
          16: {"E": 314300, "N": 424725, "RL": 2030.5},
          17: {"E": 314225, "N": 424600, "RL": 2045.5},
          18: {"E": 314100, "N": 424600, "RL": 2060.5},
          19: {"E": 313975, "N": 424575, "RL": 2075.5},
          20: {"E": 313875, "N": 424525, "RL": 2090.5}}


def rampTotalDistance(dictName, start_index, end_index):
    total_down = 0
    for i in range(start_index, end_index + 1):  # Include end_index
        #if i < end_index:  # Prevent index out of range error
        # Ramp down slope distance.
        if dictName[i + 1]["RL"] > dictName[i]["RL"]:
            ramp_down_distance = math.sqrt(
                    (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
                    (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
                    (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)
                              
            total_down += ramp_down_distance
    return total_down
    
dist = rampTotalDistance(nwC,1,20)                 

print(f"Total down distance: {dist}")

Thanks Jeff. Now I’ve changed as you suggested but it gives an error (KeyError: 21) highlighting red the dictName[i + 1] after first if.

Hi,

since you are already adding a 1 to the i index, in dict[i + i], you don’t need to add a one to the end_index + 1.

So, just use:

    for i in range(start_index, end_index):  # Include end_index
1 Like

Thanks Paul. It works.

… so that you don’t have all of those extra decimal places, you can make use of the built-in round function. The 2 stipulates the number of decimal places that you require. Change it to your specification.

print(f"Total down distance: {round(dist, 2)}")

Thanks Paul.

I’m trying to build in one function to have multiple returns.

Up slope distance

if dictName[i + 1][“RL”] > dictName[i][“RL”]:

Down slope distance.

if dictName[i + 1][“RL”] < dictName[i][“RL”]:

Flat distance

if dictName[i + 1][“RL”] == dictName[i][“RL”]:

and without this line would calculate the total distance.

Just add two more if conditional statements:

        if dictName[i + 1]["RL"]  < dictName[i]["RL"]:
            down_slope_distance = math.sqrt(
                    (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
                    (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
                    (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)

        if dictName[i + 1]["RL"]  == dictName[i]["RL"]:
            flat_distance = math.sqrt(
                    (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
                    (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
                    (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)

Then, in your return, add these two additional values into the return statement such that instead of returning one value, you are returning a tuple of values (plural).

return ramp_down_distance, down_slope_distance, flat_distance

Thanks Paul will have a go.

Alternatively, instead of indexes, one can take andvantage of itertools.pairwise and also reduce repetition:

data ={ 1:  {"E": 314650, "N": 424575, "RL": 1805.5},
        2:  {"E": 314525, "N": 424475, "RL": 1820.5},
        3:  {"E": 314400, "N": 424375, "RL": 1835.5},
        4:  {"E": 314500, "N": 424550, "RL": 1850.5},
        5:  {"E": 314550, "N": 424650, "RL": 1865.5},
        6:  {"E": 314625, "N": 424750, "RL": 1880.5},
        7:  {"E": 314700, "N": 424850, "RL": 1895.5},
        8:  {"E": 314725, "N": 424975, "RL": 1910.5},
        9:  {"E": 314700, "N": 425125, "RL": 1925.5},
        10: {"E": 314675, "N": 425250, "RL": 1940.5},
        11: {"E": 314625, "N": 425300, "RL": 1955.5},
        12: {"E": 314600, "N": 425100, "RL": 1970.5},
        13: {"E": 314600, "N": 424975, "RL": 1985.5},
        14: {"E": 314500, "N": 424800, "RL": 2000.5},
        15: {"E": 314400, "N": 424775, "RL": 2015.5},
        16: {"E": 314300, "N": 424725, "RL": 2030.5},
        17: {"E": 314225, "N": 424600, "RL": 2045.5},
        18: {"E": 314100, "N": 424600, "RL": 2060.5},
        19: {"E": 313975, "N": 424575, "RL": 2075.5},
        20: {"E": 313875, "N": 424525, "RL": 2090.5}}


d = 0
for ((first, start), (second, end)) in pairwise(data.items()):
    if start['RL'] < end['RL']:
        d += math.sqrt(sum((end[key] - start[key]) ** 2 for key in ('E', 'N','RL')))

Aivar,

Thanks…this is sleek…will have a go with this one too.

My final output…

> #################################################################################################################################
> # Some segment downslope.
> nwA    ={ 1:  {"E": 314650, "N": 424575, "RL": 1805.5},
>           2:  {"E": 314525, "N": 424475, "RL": 1820.5},
>           3:  {"E": 314400, "N": 424375, "RL": 1835.5}, # down slope.
>           4:  {"E": 314500, "N": 424550, "RL": 1825.5}, # down slope.
>           5:  {"E": 314550, "N": 424650, "RL": 1815.5}, # down slope.
>           6:  {"E": 314625, "N": 424750, "RL": 1880.5},
>           7:  {"E": 314700, "N": 424850, "RL": 1865.5}, # down slope.
>           8:  {"E": 314725, "N": 424975, "RL": 1845.5}, # down slope
>           9:  {"E": 314700, "N": 425125, "RL": 1925.5},
>           10: {"E": 314675, "N": 425250, "RL": 1940.5},
>           11: {"E": 314625, "N": 425300, "RL": 1955.5},
>           12: {"E": 314600, "N": 425100, "RL": 1970.5},
>           13: {"E": 314600, "N": 424975, "RL": 1985.5},
>           14: {"E": 314500, "N": 424800, "RL": 2000.5}, # Flat.
>           15: {"E": 314400, "N": 424775, "RL": 2000.5}, # Flat.
>           16: {"E": 314300, "N": 424725, "RL": 2000.5}, # Flat.
>           17: {"E": 314225, "N": 424600, "RL": 2045.5},
>           18: {"E": 314100, "N": 424600, "RL": 2060.5}, 
>           19: {"E": 313975, "N": 424575, "RL": 2075.5}, # Flat.
>           20: {"E": 313875, "N": 424525, "RL": 2075.5}} # Flat.
> 
> #################################################################################################################################
> # All Different Haulage Distances.
> def rampSegmentDistance(dictName, start_index, end_index):
>     total_dist  = 0
>     up_dist     = 0
>     down_dist   = 0
>     flat_dist   = 0
>     for i in range(start_index, end_index):  # Include end_index
>         if i < end_index:  # Prevent index out of range error
>             # Ramp Total distance.
>             ramp_total_distance = math.sqrt(
>                     (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
>                     (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
>                     (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)                    
>             total_dist += ramp_total_distance    
>             # Ramp Up Slope distance.
>             if dictName[i + 1]["RL"] > dictName[i]["RL"]:   
>                 ramp_up_distance = math.sqrt(
>                     (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
>                     (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
>                     (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)                 
>                 up_dist += ramp_up_distance
>             # Ramp Down Slope distance.
>             elif dictName[i + 1]["RL"] < dictName[i]["RL"]:   
>                 ramp_down_distance = math.sqrt(
>                     (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
>                     (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
>                     (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)                 
>                 down_dist += ramp_down_distance
>             # Ramp Flat distance.
>             elif dictName[i + 1]["RL"] == dictName[i]["RL"]:   
>                 ramp_flat_distance = math.sqrt(
>                     (dictName[i + 1]["E"] - dictName[i]["E"]) ** 2 +
>                     (dictName[i + 1]["N"] - dictName[i]["N"]) ** 2 +
>                     (dictName[i + 1]["RL"] - dictName[i]["RL"]) ** 2)                 
>                 flat_dist += ramp_flat_distance             
>     return total_dist, up_dist, down_dist, flat_dist
>     
> dist = rampSegmentDistance(nwA,9,20)                 
> 
> print(f"Total distances: {dist[0]}")
> print(f"Up distances: {dist[1]}")
> print(f"Down distances: {dist[2]}")
> print(f"Flat distances: {dist[3]}")