
    TiO                     z   d Z ddlZddlZd Zd Zd$dZd Zd Zej	        fdZ
ej	        fd	Z ej        d
dge          Zd$dZej	        fdZej	        fdZej	        fdZd Zej	        fdZej	        fdZej	        fdZd Zd Zd Zd Zd Zd$dZd Zd Zd Zd Z d Z!d  Z"ej	        fd!Z#d" Z$d# Z%dS )%a8  
Numpy encode/decode/utility implementations for run length encodings.

# Run Length Encoded Features

Encoding/decoding functions for run length encoded data.

We include code for two variations:

* run length encoding (RLE)
* binary run length encdoing (BRLE)

RLE stores sequences of repeated values as the value followed by its count, e.g.

```python
dense_to_rle([5, 5, 3, 2, 2, 2, 2, 6]) == [5, 2, 3, 1, 2, 4, 6, 1]
```

i.e. the value `5` is repeated `2` times, then `3` is repeated `1` time, `2` is
repeated `4` times and `6` is repeated `1` time.

BRLE is an optimized form for when the stored values can only be `0` or `1`.
This means we only need to save the counts, and assume the values alternate
(starting at `0`).

```python
dense_to_brle([1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0]) ==               [0, 2, 4, 7, 2]
```

i.e. the value zero occurs `0` times, followed by `2` ones, `4` zeros, `7` ones
and `2` zeros.

Sequences with counts exceeding the data type's maximum value have to be
handled carefully. For example, the `uint8` encoding of 300 zeros
(`uint8` has a max value of 255) is:

* RLE: `[0, 255, 0, 45]`  (`0` repeated `255` times + `0` repeated `45` times)
* BRLE: `[255, 0, 45, 0]` (`255` zeros + `0` ones + `45` zeros + `0` ones)

This module contains implementations of various RLE/BRLE operations.
    Nc                 *    t          j        |           S )z6Optimized implementation of `len(brle_to_dense(brle))`npsumbrles    Q/DATA/AppData/hermes/venv/lib/python3.11/site-packages/trimesh/voxel/runlength.pybrle_lengthr
   1   s    6$<<    c                 <    t          j        | ddd                   S )zAOptimized implementation of `len(rle_to_dense(rle_to_brle(rle)))`   N   r   )rles    r	   
rle_lengthr   6   s    6#add)r   c                 d   d}dg}d}t          j        | d          D ]X\  }}||z  }|dvrt          d          ||k    r|dxx         |z  cc<   4|                    t	          |                     |}Yt          |          dz  r|                    d           |t          ||          }|S )	a:  
    Convert run length encoded (RLE) value/counts to BRLE.

    RLE data is stored in a rank 1 array with each pair giving:
    (value, count)

    e.g. the RLE encoding of [4, 4, 4, 1, 1, 6] is [4, 3, 1, 2, 6, 1].

    Parameters
    ----------
    rle : (n,) int
      Run length encoded data

    Returns
    ----------
    equivalent binary run length encoding. a list if dtype is None,
        otherwise brle_to_brle is called on that list before returning.

    Raises
    ----------
    ValueError
      If any of the even counts of `rle` are not zero or 1.
    r   r   )r   r   z2Invalid run length encoding for conversion to BRLEr   r   Ndtype)r   reshape
ValueErrorappendintlenbrle_to_brle)r   r   curr_valoutaccvaluecounts          r	   rle_to_brler!   ;   s    0 H#C
C
300  uuQRRRHGGGuGGGGJJs5zz"""HH
3xx!| 

13e,,,Jr   c                 h    | d         s| d         rt          j        | ddgd          S | dd         S )a  
    Get the BRLE encoding of the `logical_not`ed dense form of `brle`.

    Equivalent to `dense_to_brle(np.logical_not(brle_to_dense(brle)))` but
    highly optimized - just pads brle with a 0 on each end (or strips is
    existing endpoints are both zero).

    Parameters
    ----------
    brle: rank 1 int array of binary run length encoded data

    Returns
    ----------
    rank 1 int array of binary run length encoded data corresponding to
    element-wise not of the input.
    r   r   r   constantmode)r   padr   s    r	   brle_logical_notr'   f   sD    " Aw $r( vdQF4444AbDzr   c                     t          |           dk    rg S t          | d                   g}d}| dd         D ]B}|r|dxx         |z  cc<   d}|dk    rd} |                    t          |                     C|S )z#Inverse of split_long_brle_lengths.r   Fr   Nr   T)r   r   r   )lengthsr   accumulatinglengths       r	   merge_brle_lengthsr,   }   s    
7||q	wqz??
CL!""+ ( ( 	(GGGvGGG LL{{#

3v;;''''Jr   c                 8   t          j        |           } t          j                  j        | k    }t          j        |          rt          |           }t          j        |           z  }| z                                }t          j        fdt          ||          D                       } | 	                    t          j
        |          dz  |z   f                                        } | S | j        k    r|                               S | S )a3  
    Split lengths that exceed max dtype value.

    Lengths `l` are converted into [max_val, 0] * l // max_val + [l % max_val]

    e.g. for dtype=np.uint8 (max_value == 255)
    ```
    split_long_brle_lengths([600, 300, 2, 6], np.uint8) ==              [255, 0, 255, 0, 90, 255, 0, 45, 2, 6]
    ```
    c                 T    g | ]$\  }}t          j        d g|z  |gz             %S )r   r   )r   array).0repeat	remainderr   max_vals      r	   
<listcomp>z+split_long_brle_lengths.<locals>.<listcomp>   sL       %FI '1.)<EJJJ  r   r   )r   asarrayiinfomaxanyr   astypeconcatenatezipr   r   r   )r)   r   bad_length_masknlrepeats
remaindersr3   s    `    @r	   split_long_brle_lengthsr@      s    j!!Ghuoo!G'O	vo \\*W%%0'//66
.    ),Wj)A)A  
 
 //26'??Q#6#;"=>>EEeLL	%		~~e$$$r   c                    | j         t          k    rt          d          t          | j                  dk    rt          d          t          |           }t
          j        dt          j        | dd         | dd         k              dz   f         }t          j        t
          j        ||f                   }t          ||          }| d         rt          j
        |ddgd	          }|S )
aX  
    Get the binary run length encoding of `dense_data`.

    Parameters
    ----------
    dense_data: rank 1 bool array of data to encode.
    dtype: numpy int type.

    Returns
    ----------
    Binary run length encoded rank 1 array of dtype `dtype`.

    Raises
    ----------
    ValuError if dense_data is not a rank 1 bool array.
    z`dense_data` must be boolr   z`dense_data` must be rank 1.r   Nr   r   r#   r$   )r   boolr   r   shaper   r_flatnonzerodiffr@   r&   )
dense_datar   nstartsr)   s        r	   dense_to_brlerJ      s    " 44555
:!!7888JAU1bnZ^z#2#%FGG!KKLFgbeFAI&''G%gU;;;G!} ;&1a&z:::Nr   FTr   c                    |t           }n6t          j        |          }|j        dk    rt	          d|j                   t          j        t           t          j        ddf         t          |           dz   dz  d                                          }t          j        |dt          |                    t          j        | t                                                              S )	a  Decode binary run length encoded data to dense.

    Parameters
    ----------
    brle_data: BRLE counts of False/True values
    vals: if not `None`, a length 2 array/list/tuple with False/True substitute
        values, e.g. brle_to_dense([2, 3, 1, 0], [7, 9]) == [7, 7, 9, 9, 9, 7]

    Returns
    ----------
    rank 1 dense data of dtype `bool if vals is None else vals.dtype`

    Raises
    ----------
    ValueError if vals it not None and shape is not (2,)
    N)r   zvals.shape must be (2,), got r   r   r   axisr   )
_ftr   r5   rC   r   r1   newaxisr   flattenr   )	brle_datavalsfts      r	   brle_to_denserT      s    " |z$:ITZIIJJJ	3rz111}%I(:q'@q	I	I	I	Q	Q	S	SB9R(#i..()2:is+K+K+KLLTTVVVr   c           	      B   t          j        t          j        | d          dd          \  }}|t          j        ||          }	 t          j        t          j        |d          t          j        |d                              t                              }n# t          $ ru t          j        t          j        |                    t           j	                  d          t          j        |                    t                    d                    }Y nw xY w|S )zAGet the dense decoding of the associated run length encoded data.r   r   r   rL   Nr   )
r   splitr   
asanyarrayr1   squeezer9   r   	TypeErrorint64)rle_datar   valuescountsresults        r	   rle_to_denser_      s   Xbj7;;QRHHHNFFvU333	
JvB'''F)D)D)D)K)KC)P)P
 
  
 
 
Jv}}RX..R888Jv}}S))333
 

 Ms   AB A<DDc                 x   t          |           }t          j        dt          j        | dd         | dd         k              dz   f         }t          j        t          j        ||f                   }| |         }t          |||          \  }}t          j        ||fd          }|                                S )z3Get run length encoding of the provided dense data.r   r   Nr   r   rL   )r   r   rD   rE   rF   split_long_rle_lengthsstackrP   )rG   r   rH   rI   r)   r\   r   s          r	   dense_to_rlerc     s    JAU1bnZ^z#2#%FGG!KKLFgbeFAI&''GF,VWEJJJOFG
(FG$1
-
-
-C;;==r   c                 ,   t          j        |          j        }t          j        |t           j                  }||z  }|                                r|dz                       t                    }||z  }t          j        | |          } t          j	        t          |          |          }|                    |           t          j        ||          }||t          j        |          dz
  <   n |j        |k    r|                    |          }| |fS )a=  
    Split long lengths in the associated run length encoding.

    e.g.
    ```python
    split_long_rle_lengths([5, 300, 2, 12], np.uint8) == [5, 255, 5, 45, 2, 12]
    ```

    Parameters
    ----------
    values: values column of run length encoding, or `rle[::2]`
    lengths: counts in run length encoding, or `rle[1::2]`
    dtype: numpy data type indicating the maximum value.

    Returns
    ----------
    values, lengths associated with the appropriate splits. `lengths` will be
    of type `dtype`, while `values` will be the same as the value passed in.
    r   r   )r   r6   r7   r5   rZ   r8   r9   r   r1   zerosr   fillcumsumr   )r\   r)   r   
max_lengthr>   r2   s         r	   ra   ra     s    ( %$Jj111G#G{{}} 	(Q;&&s++j(	67++(3w<<u555Z   )GW--*3	'""Q&''	%		..''7?r   c                     g }g }d}t          | |          D ]\\  }}|dk    r||k    r|dxx         |z  cc<   #|}|                    t          |                     |                    |           ]||fS )zEInverse of split_long_rle_lengths except returns normal python lists.Nr   r   )r;   r   r   )r\   r)   
ret_valuesret_lengthscurrr   r+   s          r	   merge_rle_lengthsrm   0  s    JKDVW-- % %vQ;;D==OOOv%OOOODs6{{+++e$$$${""r   c                 &   t          |           dz  dk    rt          j        | dgg          } | }t          j        t          t          |           dz            }t          t          j        ||fd                                          |          S )Nr   r   r   rL   r   )r   r   r:   tilerN   
rle_to_rlerb   rP   )r   r   r)   r\   s       r	   brle_to_rlerq   A  s    
4yy1}~taSk**GWS#d))q.))Fbh0q999AACC5QQQQr   c                 >    t          t          |           |          S )\
    Almost the identity function.

    Checks for possible merges and required splits.
    r   )r@   r,   )r   r   s     r	   r   r   I  s      ##5d#;#;5IIIIr   c                     t          j        | d          j        \  }}t          ||          \  }}t	          |||          \  }}t          j        ||fd                                          S )rs   r   r   r   rL   )r   r   Trm   ra   rb   rP   )r   r   r\   r)   s       r	   rp   rp   R  sm     jg..0OFG'88OFG,VWEJJJOFG8VW%A...66888r   c                     t          | t          j                  st          j        | d          } t          j        |           |          dfd	}|S )NFcopyc                     t          j        t                    |pt          | dd                     }t	           |                     |<   |S )Nr   r   )r   re   r   getattrtuple)datar   r^   orderordered_indicessorted_gather_fns      r	   fz_unsorted_gatherer.<locals>.fd  sR    #e**E,QWT7D5Q5QRRR..t_EEFFur   N)
isinstancer   ndarrayr/   argsort)indicesr   r   r}   r~   s    ` @@r	   _unsorted_gathererr   ^  st    grz** 0(7///JwEenO       
 Hr   c              #     K   t          |           }t          |          }	 t          |          }n# t          $ r Y dS w xY wd}	 ||k    rH	 t          |          }|t          |          z  }n# t          $ r t          d||          w xY w||k    H	 ||k     r|V  t          |          }||k     n# t          $ r Y dS w xY w)a  
    Gather brle_data at ordered_indices.

    This is equivalent to `rle_to_dense(brle_data)[ordered_indices]` but avoids
    the decoding.

    Parameters
    ----------
    brle_data: iterable of run-length-encoded data.
    ordered_indices: iterable of ints in ascending order.

    Returns
    ----------
    `brle_data` iterable of values at the dense indices, same length as
    ordered indices.
    Nr   T-Index %d out of range of raw_values length %diternextStopIteration
IndexError)r[   r~   	data_iter
index_iterindexstartr   s          r	   sorted_rle_gather_1dr   l  s#     " XIo&&JZ     EunnYi(     CUE  	 unn	%--Z(( %--  	 	 	EE	s,   2 
A A !A/ /BB5 5
CCc              #      K   t          |           }t          |          }	 	 t          |          }t          |          }n# t          $ r Y dS w xY wt          |          D ]}t          |          }|r|V  Y)a!  
    Perform masking of the input run-length data.

    Parameters
    ----------
    rle_data: iterable of run length encoded data
    mask: iterable of bools corresponding to the dense mask.

    Returns
    ----------
    iterable of dense values of rle_data wherever mask is True.
    TNr   r   r   ranger[   maskr   	mask_iterr   r    _ms           r	   rle_maskr     s       XIT

I		OOEOOEE 	 	 	EE	u 	 	AYA 	s   A 
AAc              #      K   t          |           }t          |          }d}	 	 | }t          |          }n# t          $ r Y dS w xY wt          |          D ]}t          |          }|r|V  M)a.  
    Perform masking of the input binary run-length data.

    Parameters
    ----------
    brle_data: iterable of binary run length encoded data
    mask: iterable of bools corresponding to the dense mask.

    Returns
    ----------
    iterable dense values of brle_data wherever mask is True.
    TNr   r   s           r	   	brle_maskr     s       XIT

IE		IEOOEE 	 	 	EE	u 	 	AYA 	s   8 
AAc                 ,    t          | t                    S )a8  
    Get a gather function at the given indices.

    Because gathering on RLE data requires sorting, for instances where
    gathering at the same indices on different RLE data this can save the
    sorting process.

    If only gathering on a single RLE iterable, use `rle_gather_1d`.

    Parameters
    ----------
    indices: iterable of integers

    Returns
    ----------
    gather function, mapping `(rle_data, dtype=None) -> values`.
    `values` will have the same length as `indices` and dtype provided,
    or rle_data.dtype if no dtype is provided.
    )r   r   r   s    r	   rle_gatherer_1dr     s    ( g';<<<r   c                 6     t          |          | |          S )a   
    Gather RLE data values at the provided dense indices.

    This is equivalent to `rle_to_dense(rle_data)[indices]` but the
    implementation does not require the construction of the dense array.

    If indices is known to be in order, use `sorted_gather_1d`.

    Parameters
    ----------
    rle_data: run length encoded data
    indices: dense indices
    dtype: numpy dtype. If not provided, uses rle_data.dtype

    Returns
    ----------
    numpy array, dense data at indices, same length as indices and dtype as
    rle_data
    r   )r   )r[   r   r   s      r	   rle_gather_1dr     s!    ( $?7##HE::::r   c              #   z  K   t          |           }t          |          }	 t          |          }n# t          $ r Y dS w xY wd}d}	 ||k    r<	 | }|t          |          z  }n# t          $ r t          d||          w xY w||k    <	 ||k     r|V  t          |          }||k     n# t          $ r Y dS w xY wu)a  
    Gather brle_data at ordered_indices.

    This is equivalent to `brle_to_dense(brle_data)[ordered_indices]` but
    avoids the decoding.

    Parameters
    ----------
    raw_data: iterable of run-length-encoded data.
    ordered_indices: iterable of ints in ascending order.

    Returns
    ----------
    `raw_data` iterable of values at the dense indices, same length as
    ordered indices.
    Nr   Tr   r   )rQ   r~   r   r   r   r   r   s          r	   sorted_brle_gather_1dr     s$     " YIo&&JZ     EEunn!	i(     CUE  	 unn	%--Z(( %--  	 	 	EE	s,   2 
A A A% %BB+ +
B98B9c                 ^    t          j        t          | t                    t                    S )a:  
    Get a gather function at the given indices.

    Because gathering on BRLE data requires sorting, for instances where
    gathering at the same indices on different RLE data this can save the
    sorting process.

    If only gathering on a single RLE iterable, use `brle_gather_1d`.

    Parameters
    ----------
    indices: iterable of integers

    Returns
    ----------
    gather function, mapping `(rle_data, dtype=None) -> values`.
    `values` will have the same length as `indices` and dtype provided,
    or rle_data.dtype if no dtype is provided.
    r   )	functoolspartialr   r   rB   r   s    r	   brle_gatherer_1dr   &  s.    ( 7$9::$   r   c                 2     t          |          |           S )a  
    Gather BRLE data values at the provided dense indices.

    This is equivalent to `rle_to_dense(rle_data)[indices]` but the
    implementation does not require the construction of the dense array.

    If indices is known to be in order, use `sorted_brle_gather_1d`.

    Parameters
    ----------
    rle_data: run length encoded data
    indices: dense indices

    Returns
    ----------
    numpy array, dense data at indices, same length as indices and dtype as
    rle_data
    )r   )rQ   r   s     r	   brle_gather_1dr   ?  s    & %G$$Y///r   c                     t          |           dz  dk    rt          j        | dggd          } | d         dk    rdnd}| d|d         S )z>Equivalent to dense_to_brle(brle_to_dense(brle_data)[-1::-1]).r   r   rL   r   N)r   r   r:   )rQ   ends     r	   brle_reverser   U  s[    
9~~QNIs#3!<<<	"""""CRBYr   c                     t          | t          j                  st          j        | d          } t          j        | d          } | ddd         } t          j        | d          S )z1Get the rle encoding of the reversed dense array.Frw   r   r   Nr   )r   r   r   r/   r   )r[   s    r	   rle_reverser   ]  s]    h
++ 28H5111z(G,,HBH:h&&&r   c                 0   g }g }t          |           }d}	 	 t          |          }t          t          |                    }||z   }|r\|                    t	          j        ||t          j                             |                    t	          j        ||                     |}# t          $ r Y nw xY wt          |          dk    rt          |          dk    sJ ||fS t	          j
        |          }t	          j
        || j                  }||fS )z,Get dense indices associated with non-zeros.r   Tr   )r   r   r   r   r   arangerZ   r1   r   r   r:   r   )r[   r   r\   itr   r   r]   r   s           r	   rle_to_sparser   f  s#   GF	hBE
	HHEb]]F&.C 8ry28DDDEEEbiv66777E	    
7||q6{{anW%%G^F(.999FF?s   BB) )
B65B6c                     t          j        |           }fdt          |d d d         |dd d                   D             }t          j        |          S )Nc                 D    g | ]\  }}t          j        ||           S )r   )r   r   )r0   ser   s      r	   r4   z"brle_to_sparse.<locals>.<listcomp>  s.    SSS1ryAU+++SSSr   r   r   )r   rg   r;   r:   )rQ   r   endsr   s    `  r	   brle_to_sparser     sY    9YDSSSSD1ItADqDz8R8RSSSG>'"""r   c                 ~   t          j        | d          } d}t          |           }t          |           D ]\  }\  }}|r
|dk    r|} n||z  }d}t          |           }t          | ddd                   D ]\  }\  }}|r
|dk    r|} n||z  }| ||dk    rdn|                              d          } | ||ffS )a!  
    Remove leading and trailing zeros.

    Parameters
    ----------
    rle_data: run length encoded data

    Returns
    ----------
    (stripped_rle_data, padding)
        stripped_rle_data: rle data without any leading or trailing zeros
        padding: 2-element dense padding
    r   r   Nr   r   )r   r   r   	enumerate)	r[   r   final_iivalr    r   final_jjs	            r	   	rle_stripr     s    z(G,,HE(mmG$X..  <C 	5199GEUNEE
C(mmG$Xddd^44  <C 	5199GE5LCC'Q,,$$WHDEMMeTTHeS\!!r   c                    d}d}t          |           }t          |           D ]\  }}| }|r
|dk    r|} n||z  }d}t          |           }t          t          |           dz            }t          | ddd                   D ]\  }}| }|r
|dk    r|} n||z  }| ||dk    rdn|          } t          j        dg| g          } | ||ffS )a$  
    Remove leading and trailing zeros.

    Parameters
    ----------
    brle_data: binary run length encoded data.

    Returns
    ----------
    (stripped_brle_data, padding)
    stripped_brle_data: rle data without any leading or trailing zeros
    padding: 2-element dense padding
    r   Tr   Nr   )r   r   rB   r   r:   )	rQ   r   r   r   r   r    r   r   r   s	            r	   
brle_stripr     s    E
C)nnGi((  5g 	5199GEUNEE
C)nnG
s9~~!
"
"Ci"o..  5g 	5199GE5LCC'GqLLDDwhFGIY/00Iucl""r   r   )&__doc__r   numpyr   r
   r   r!   r'   r,   rZ   r@   rJ   r/   rB   rN   rT   r_   rc   ra   rm   rq   r   rp   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r	   <module>r      s  ) )V          
  
( ( ( (V  .  & ,.8        F %'H    < bht}D)))W W W W6 "$    $ $&8     35( ! ! ! !H# # #" H R R R R  X J J J J ( 	9 	9 	9 	9  ' ' 'T  6  8= = =.; ; ; ;.( ( (V  20 0 0,     ' ' '  4 %'H # # # #"" "" ""J%# %# %# %# %#r   