Ë
    :vžj&i  ã                   ó¦  — d Z ddlZddlmZ ddlmZmZ ddlm	Z	m
Z
mZmZmZ 	 ddlmZ 	 	 	 	 	 d/d	edz  d
edz  de
dz  de
dz  de
dz  f
d„Zd0de
dz  de
dz  fd„Z	 d1de	de
dz  dedefd„Zd2de
dz  deej0                     fd„Z	 d3de	dedefd„Z	 	 	 d4de	de
dedefd„Zd2de	de
dz  fd „Z	 	 	 d5dedede
dz  fd!„Zd6d"„Zd2d#„Zd0d$„Z ejB                  fd%e	d&e	deej0                     fd'„Z"d7d(„Z#de	d)ede$eejJ                     ef   fd*„Z&d+„ Z'd,ejP                  dddfd-„Z)d.„ Z*y# e$ r#ZddlmZ  ej&                  e«      ZY dZ[�Œ!dZ[ww xY w)8zD
grouping.py
-------------

Functions for grouping values and rows.
é    Né   )Úutil)ÚlogÚtol)Ú	ArrayLikeÚIntegerÚNDArrayÚNumberÚSequence)ÚcKDTree)Ú
exceptionsÚ	merge_texÚ
merge_normÚdigits_vertexÚdigits_normÚ	digits_uvc                 óX  — t        | j                  «      dk(  ry|€d}|€d}|€d}|€d}|€#t        j                  t        j
                  «      }t        | d«      rVt        | j                  «      dkD  r>t        j                  t        | j                  «      t        ¬«      }d|| j                  <   n.t        j                  t        | j                  «      t        ¬«      }| j                  d	|z  z  g}|s¥| j                  j                  r�| j                  j                  d
k(  rv| j                  j                  �`t        | j                  j                  «      t        | j                  «      k(  r+|j!                  | j                  j                  d	|z  z  «       | j"                  d   }|sCt        j$                  |«      | j                  j$                  k(  r|j!                  |d	|z  z  «       t        j&                  |«      j)                  «       j+                  t        j,                  «      }t/        ||   d¬«      \  }	}
t        j                  t        | j                  «      t        j,                  ¬«      }|
||<   t        j0                  |«      d   |	   }| j3                  ||¬«       y)a±  
    Removes duplicate vertices, grouped by position and
    optionally texture coordinate and normal.

    Parameters
    -------------
    mesh : Trimesh object
      Mesh to merge vertices on
    merge_tex : bool
      If True textured meshes with UV coordinates will
      have vertices merged regardless of UV coordinates
    merge_norm : bool
      If True, meshes with vertex normals will have
      vertices merged ignoring different normals
    digits_vertex : None or int
      Number of digits to consider for vertex position
    digits_norm : int
      Number of digits to consider for unit normals
    digits_uv : int
      Number of digits to consider for UV coordinates
    r   NFé   é   Úfaces©ÚdtypeTé
   ÚtextureÚvertex_normals)Ú
keep_order)ÚmaskÚinverse)ÚlenÚverticesr   Údecimal_to_digitsr   ÚmergeÚhasattrr   ÚnpÚzerosÚboolÚonesÚvisualÚdefinedÚkindÚuvÚappendÚ_cacheÚshapeÚcolumn_stackÚroundÚastypeÚint64Úunique_rowsÚnonzeroÚupdate_vertices)Úmeshr   r   r   r   r   Ú
referencedÚstackedÚnormalsÚuÚir   r   s                úa/workspace/moltex-experiments/.pixi/envs/default/lib/python3.12/site-packages/trimesh/grouping.pyÚmerge_verticesr=      s  € ô< ˆ4�=‰=Ó˜QÒØØÐØˆ	ØÐØˆ
ØÐØˆØÐØˆ	ØÐä×.Ñ.¬s¯y©yÓ9ˆô ˆt�WÔ¤# d§j¡j£/°AÒ"5Ü—X‘Xœc $§-¡-Ó0¼Ô=ˆ
Ø!%ˆ
�4—:‘:Òô —W‘WœS §¡Ó/´tÔ<ˆ
ð �}‰}  MÑ 1Ñ2Ð3€Gñ
 Ø�K‰K×ÒØ�K‰K×Ñ 	Ò)Ø�K‰K�N‰NÐ&Ü�—‘—‘Ó¤3 t§}¡}Ó#5Ò5ð 	�‰�t—{‘{—~‘~¨¨Y©Ñ7Ô8ð �k‰kÐ*Ñ+€GÙœ"Ÿ(™( 7Ó+¨t¯}©}×/BÑ/BÒBØ�‰�w " k¡/Ñ2Ô3ô �o‰o˜gÓ&×,Ñ,Ó.×5Ñ5´b·h±hÓ?€Gô �w˜zÑ*°tÔ<�D€A€qô �h‰h”s˜4Ÿ=™=Ó)´·±Ô:€GØ€GˆJÑä�:‰:�jÓ! !Ñ$ QÑ'€Dà×Ñ˜d¨GÐÕ4ó    Úmin_lenÚmax_lenc                 óÖ  — t        j                  | «      }|j                  «       }||   } | j                  j                  dk(  rKt        j
                  t        j                  t        j                  | «      «      t        j                  «      }n| dd | dd k7  }t        j                  dt        j                  |«      d   dz   «      }t        j                  t        |«      t        ¬«      }t        j                  t        j                  |t        | «      gf«      «      }|€|�|�|||k\  z  }|�|||k  z  }t!        ||   ||   «      D �	�
cg c]  \  }	}
||	|	|
z    ‘Œ }}	}
|S c c}
}	w )aÅ  
    Return the indices of values that are identical

    Parameters
    ----------
    values : (n,) int
      Values to group
    min_len : int
      The shortest group allowed
      All groups will have len >= min_length
    max_len : int
      The longest group allowed
      All groups will have len <= max_length

    Returns
    ----------
    groups : sequence
      Contains indices to form groups
      IE [0,1,0,1] returns [[0,2], [1,3]]
    Úfr   Néÿÿÿÿr   r   )r$   Ú
asanyarrayÚargsortr   r*   ÚgreaterÚabsÚdiffr   Úzeror,   r4   r'   r   r&   ÚconcatenateÚzip)Úvaluesr?   r@   ÚoriginalÚorderÚnondupeÚdupe_idxÚdupe_okÚdupe_lenr;   ÚjÚgroupss               r<   ÚgrouprU   q   sS  € ô* �}‰}˜VÓ$€Hð ×ÑÓ€EØ�e‰_€Fð ‡|�|×Ñ˜CÒô —*‘*œRŸV™V¤B§G¡G¨F£OÓ4´c·h±hÓ?‰ð
 ˜˜�*  s¨ Ñ+ˆä�y‰y˜œBŸJ™J wÓ/°Ñ2°QÑ6Ó7€Hô �g‰g”c˜(“m¬4Ô0€Gô �w‰w”r—~‘~ x´#°f³+°Ð&?Ó@ÓA€Hð Ð˜gÐ1ØÐØ�x 7Ñ*Ñ*ˆGØÐØ�x 7Ñ*Ñ*ˆGä-0°¸'Ñ1BÀHÈWÑDUÔ-VÔWÑ-V¡T Q¨ˆe�A˜˜Q™Ò Ð-V€FÑWØ€Mùó Xs   ÅE%ÚdataÚdigitsÚ	allow_intÚreturnc                 ó  — t        | «      dk(  r%t        j                  g t        j                  ¬«      S t	        | |¬«      }t        |j
                  «      dk(  r|S |�rt        |j
                  «      dk(  �r|j
                  d   dk  rôt        t        j                  d|j
                  d   z  «      «      }|j                  «       |j                  «       }}d|dz
  z  dz
  }||k  r–|| kD  r�t        j                  t        |«      t        j                  ¬«      }|j                  |dz   z   j                  t        j                  «      }	t        |	«      D ]#  \  }
}t        j                  |||
|z  z  |¬«       Œ% |S t        j                  t        j                   |j                  j"                  |j
                  d   z  f«      }t        j$                  |«      j'                  |«      j)                  d	«      }d
|j*                  d<   |S )a¡  
    We turn our array into integers based on the precision
    given by digits and then put them in a hashable format.

    Parameters
    ---------
    data : (n, m) array
      Input data
    digits : int or None
      How many digits to add to hash if data is floating point
      If None, tol.merge will be used

    Returns
    ---------
    hashable : (n,)
      May return as a `np.void` or a `np.uint64`
    r   r   ©rW   r   r   r   é@   )ÚoutrC   FÚ	WRITEABLE)r   r$   ÚarrayÚuint64Úfloat_to_intr.   ÚintÚfloorÚminÚmaxr%   ÚTr1   Ú	enumerateÚbitwise_xorr   ÚvoidÚitemsizeÚascontiguousarrayÚviewÚreshapeÚflags)rV   rW   rX   Úas_intÚ	precisionÚd_minÚd_maxÚ	thresholdÚhashableÚbitbangÚoffsetÚcolumnr   Úresults                 r<   Úhashable_rowsry   ª   s§  € ô* ˆ4ƒy�A‚~Ü�x‰x˜¤"§)¡)Ô,Ð,ô ˜$ vÔ.€Fô ˆ6�<‰<Ó˜AÒØˆò ”S˜Ÿ™Ó&¨!Ó+°·±¸Q±À1Ò0DäœŸ™  f§l¡l°1¡oÑ!5Ó6Ó7ˆ	ð —z‘z“| V§Z¡Z£\ˆuˆð ˜9 q™=Ñ)¨QÑ.ˆ	ð �9Ò ¨)¨Ò!3ä—x‘x¤ F£´2·9±9Ô=ˆHð —x‘x 9¨q¡=Ñ1×9Ñ9¼"¿)¹)ÓDˆGô #,¨GÖ"4‘�˜ä—‘˜x¨°F¸YÑ4FÑ)GÈXÖVð #5ð ˆOô �H‰H”b—g‘g˜vŸ|™|×4Ñ4°v·|±|ÀA±ÑFÐGÓH€Eä×!Ñ! &Ó)×.Ñ.¨uÓ5×=Ñ=¸bÓA€FØ %€F‡L�L�Ñà€Mr>   c                 ó˜  — t        j                  | «      } | j                  t         j                  k(  r| S | j                  j                  dv s| j
                  dk(  r| j                  t         j                  «      S | j                  j                  dk7  r| j                  t         j                  «      } |€$t        j                  t        j                  «      }n8t        |t        t         j                  f«      st        dt!        |«      › d�«      ‚t        j"                  | d|z  z  dz
  «      j                  t         j                  «      S )a+  
    Given a numpy array of float/bool/int, return as integers.

    Parameters
    -------------
    data :  (n, d) float, int, or bool
      Input data
    digits : float or int
      Precision for float conversion

    Returns
    -------------
    as_int : (n, d) int
      Data as integers
    Úiubr   rB   z%Digits must be `None` or `int`, not `Ú`r   g�íµ ÷Æ°>)r$   rD   r   r2   r*   Úsizer1   Úfloat64r   r!   r   r"   Ú
isinstancerb   ÚintegerÚ	TypeErrorÚtyper0   )rV   rW   s     r<   ra   ra   ì   së   € ô" �=‰=˜Ó€Dð ‡z�z”R—X‘XÒØˆØ	�‰�‰˜EÑ	! T§Y¡Y°!¢^Ø�{‰{œ2Ÿ8™8Ó$Ð$Ø	�‰�‰˜CÒ	à�{‰{œ2Ÿ:™:Ó&ˆà€~ä×'Ñ'¬¯	©	Ó2‰Ü˜¤¤b§j¡jÐ 1Ô2ÜÐ?ÄÀVÃ¸~ÈQÐOÓPÐPô
 �8‰8�T˜B ™JÑ&¨$Ñ.Ó/×6Ñ6´r·x±xÓ@Ð@r>   FÚreturn_indexÚreturn_inversec                 óð   — t        j                  | dd¬«      \  }}}|j                  «       }|s|s||   S ||   g}|r|j                  ||   «       |r"|j                  |j                  «       |   «       |S )aL  
    Returns the same as np.unique, but ordered as per the
    first occurrence of the unique value in data.

    Examples
    ---------
    In [1]: a = [0, 3, 3, 4, 1, 3, 0, 3, 2, 1]

    In [2]: np.unique(a)
    Out[2]: array([0, 1, 2, 3, 4])

    In [3]: trimesh.grouping.unique_ordered(a)
    Out[3]: array([0, 3, 4, 1, 2])
    T©rƒ   r„   )r$   ÚuniquerE   r,   )rV   rƒ   r„   r‡   Úindexr   rN   rx   s           r<   Úunique_orderedr‰     sx   € ô,  ŸY™Y t¸$ÈtÔTÑ€FˆE�7ð �M‰M‹O€Eá¡Ø�e‰}Ðð �U‰mˆ_€Fáà�‰�e˜E‘lÔ#Ùà�‰�e—m‘m“o gÑ.Ô/à€Mr>   rL   Ú	minlengthÚreturn_countsc                 ó6  — t        j                  | «      } t        | j                  «      dk7  s| j                  j
                  dk7  rt        d«      ‚	 t        j                  | |¬«      }|j                  t        «      }t        j                  |«      d   }|f}|r!t        j                  |«      dz
  |    }||fz  }|r||   }	||	fz  }t        |«      dk(  r|d   S |S # t        $ r0 t        j                  d«       t        j                  | ||¬«      cY S w xY w)ai  
    For arrays of integers find unique values using bin counting.
    Roughly 10x faster for correct input than np.unique

    Parameters
    --------------
    values : (n,) int
      Values to find unique members of
    minlength : int
      Maximum value that will occur in values (values.max())
    return_inverse : bool
      If True, return an inverse such that unique[inverse] == values
    return_counts : bool
      If True, also return the number of times each
      unique item appears in values

    Returns
    ------------
    unique : (m,) int
      Unique values in original array
    inverse : (n,) int, optional
      An array such that unique[inverse] == values
      Only returned if return_inverse is True
    counts : (m,) int, optional
      An array holding the counts of each unique item in values
      Only returned if return_counts is True
    r   r;   zinput must be 1D integers!)rŠ   zcasting failed, falling back!)r„   r‹   r   )r$   rD   r   r.   r   r*   Ú
ValueErrorÚbincountr�   r   Úwarningr‡   r1   r&   ÚwhereÚcumsum)
rL   rŠ   r„   r‹   ÚcountsÚ
unique_binr‡   Úretr   Úunique_countss
             r<   Úunique_bincountr–   A  s  € ôB �]‰]˜6Ó"€FÜ
ˆ6�<‰<Ó˜AÒ §¡×!2Ñ!2°cÒ!9ÜÐ5Ó6Ð6ð	
ä—‘˜V¨yÔ9ˆð —‘œtÓ$€Jô �X‰X�jÓ! !Ñ$€FØˆ)€Cáä—9‘9˜ZÓ(¨1Ñ,¨fÑ5ˆØ�ˆzÑˆáØ˜v™ˆØ�ÐÑˆä
ˆ3ƒx�1‚}Ø�1‰vˆØ€Jøô9 ò 
ä�‰Ð3Ô4ä�y‰yØ >Àô
ò 	
ð	
ús   ÁC Ã6DÄDc                 ó  — |€t         j                  }nd| z  }t        j                  | «      } t        j                  t        | «      t        ¬«      }d|d<   t        j                  | dd | dd z
  «      |kD  |dd | |   S )aW  
    Merge duplicate sequential values. This differs from unique_ordered
    in that values can occur in multiple places in the sequence, but
    only consecutive repeats are removed

    Parameters
    -----------
    data: (n,) float or int

    Returns
    --------
    merged: (m,) float or int

    Examples
    ---------
    In [1]: a
    Out[1]:
    array([-1, -1, -1,  0,  0,  1,  1,  2,  0,
            3,  3,  4,  4,  5,  5,  6,  6,  7,
            7,  8,  8,  9,  9,  9])

    In [2]: trimesh.grouping.merge_runs(a)
    Out[2]: array([-1,  0,  1,  2,  0,  3,  4,  5,  6,  7,  8,  9])
    Nr   r   Tr   r   rC   )r   r"   r$   rD   r%   r   r&   rG   )rV   rW   Úepsilonr   s       r<   Ú
merge_runsr™   ˆ  s|   € ð2 €~Ü—)‘)‰à˜&˜‘/ˆä�=‰=˜Ó€DÜ�8‰8”C˜“I¤TÔ*€DØ€Dˆ�GÜ�v‰v�d˜1˜2�h  c r Ñ*Ó+¨gÑ5€Dˆˆ€Hà�‰:Ðr>   c                 óü   — t        j                  | «      } t        | |«      }t        j                  |dd¬«      \  }}}|s|s| |   S | |   g}|r|j	                  |«       |r|j	                  |«       t        |«      S )zÍ
    Identical to the numpy.unique command, except evaluates floating point
    numbers, using a specified number of digits.

    If digits isn't specified, the library default TOL_MERGE will be used.
    Tr†   )r$   rD   ra   r‡   r,   Útuple)	rV   rƒ   r„   rW   ro   Ú_junkr‡   r   rx   s	            r<   Úunique_floatr�   ®  sz   € ô �=‰=˜Ó€DÜ˜$ Ó'€FÜŸY™Y v¸DÐQUÔVÑ€Eˆ6�7á¡>Ø�F‰|Ðà�6‰lˆ^€FáØ�‰�fÔÙØ�‰�gÔÜ�‹=Ðr>   c                 óx   — t        | |¬«      }|rt        |dd¬«      dd S t        j                  |dd¬«      dd S )aè  
    Returns indices of unique rows. It will return the
    first occurrence of a row that is duplicated:
    [[1,2], [3,4], [1,2]] will return [0,1]

    Parameters
    ---------
    data : (n, m) array
      Floating point data
    digits : int or None
      How many digits to consider

    Returns
    --------
    unique :  (j,) int
      Index in data which is a unique row
    inverse : (n,) int
      Array to reconstruct original
      Example: data[unique][inverse] == data
    r[   Tr†   r   N)ry   r‰   r$   r‡   )rV   rW   r   Úrowss       r<   r3   r3   Ê  sG   € ô, ˜ fÔ-€Dñ ä˜d°ÀdÔKÈAÈBÐOÐOô �9‰9�T¨¸TÔBÀ1À2ÐFÐFr>   c                 ó
  — |€t        j                  | «      }t        j                  | «      } t        j                  | t        d¬«      }|D ]5  }t        j
                  | |«      }|j                  d¬«      dk(  }||   ||<   Œ7 |S )a´  
    For a 2D array of integers find the position of a
    value in each row which only occurs once.

    If there are more than one value per row which
    occur once, the last one is returned.

    Parameters
    ----------
    data :   (n, d) int
      Data to check values
    unique : (m,) int
      List of unique values contained in data.
      Generated from np.unique if not passed

    Returns
    ---------
    result : (n, d) bool
      With one or zero True values per row.


    Examples
    -------------------------------------
    In [0]: r = np.array([[-1,  1,  1],
                          [-1,  1, -1],
                          [-1,  1,  1],
                          [-1,  1, -1],
                          [-1,  1, -1]], dtype=np.int8)

    In [1]: unique_value_in_row(r)
    Out[1]:
           array([[ True, False, False],
                  [False,  True, False],
                  [ True, False, False],
                  [False,  True, False],
                  [False,  True, False]], dtype=bool)

    In [2]: unique_value_in_row(r).sum(axis=1)
    Out[2]: array([1, 1, 1, 1, 1])

    In [3]: r[unique_value_in_row(r)]
    Out[3]: array([-1,  1, -1,  1,  1], dtype=int8)
    F)r   Úsubokr   ©Úaxis)r$   r‡   rD   Ú
zeros_liker&   ÚequalÚsum)rV   r‡   rx   ÚvalueÚtestÚtest_oks         r<   Úunique_value_in_rowrª   ì  sz   € ðX €~Ü—‘˜4“ˆÜ�=‰=˜Ó€DÜ�]‰]˜4¤t°5Ô9€FÛˆÜ�x‰x˜˜eÓ$ˆØ—(‘( �(Ó" aÑ'ˆØ˜w™-ˆˆwŠð ð €Mr>   c                 óø  — t        | |¬«      }|€t        |«      S |j                  «       }||   }|dd |dd k7  }t        j                  dt        j
                  |«      d   dz   «      }t        j                  t        j                  |t        |«      gf«      «      |k(  }t        j                  ||   j                  d«      |«      t        j                  |«      z   }||   }	|dk(  r|	j                  d«      S |	S )aÏ  
    Returns index groups of duplicate rows, for example:
    [[1,2], [3,4], [1,2]] will return [[0,2], [1]]


    Note that using require_count allows numpy advanced
    indexing to be used in place of looping and
    checking hashes and is ~10x faster.


    Parameters
    ----------
    data : (n, m) array
      Data to group
    require_count : None or int
      Only return groups of a specified length, eg:
      require_count =  2
      [[1,2], [3,4], [1,2]] will return [[0,2]]
    digits : None or int
    If data is floating point how many decimals
    to consider, or calculated from tol.merge

    Returns
    ----------
    groups : sequence (*,) int
      Indices from in indicating identical rows.
    r[   Nr   rC   r   )rC   r   )ry   rU   rE   r$   r,   r4   rH   rJ   r   Útilerm   Úarange)
rV   Úrequire_countrW   rt   rN   ÚduperP   Ústart_okrT   Ú
groups_idxs
             r<   Ú
group_rowsr²   #  sÿ   € ô< ˜T¨&Ô1€Hð ÐÜ�X‹Ðð ×ÑÓ€Eà˜‰€Hð �A�Bˆ<˜8 C R˜=Ñ(€Dô �y‰y˜œBŸJ™J tÓ,¨QÑ/°!Ñ3Ó4€Hô �w‰w”r—~‘~ x´#°h³-°Ð&AÓBÓCÀ}ÑT€HÜ�W‰W�X˜hÑ'×/Ñ/°Ó8¸-ÓHÌ2Ï9É9ØóLñ €Fð �v‘€Jà˜ÒØ×!Ñ! "Ó%Ð%ØÐr>   ÚaÚbc                 ó  — t        j                  | t         j                  ¬«      } t        j                  |t         j                  ¬«      }| j                  d| j                  fg| j
                  d   z  «      j                  «       }|j                  d|j                  fg|j
                  d   z  «      j                  «       } |||«      j                  | j                  «      j                  d| j
                  d   «      S )a£  
    Find the rows in two arrays which occur in both rows.

    Parameters
    ---------
    a: (n, d) int
        Array with row vectors
    b: (m, d) int
        Array with row vectors
    operation : function
        Numpy boolean set operation function:
          -np.intersect1d
          -np.setdiff1d

    Returns
    --------
    shared : (p, d) int64
       Array containing requested rows in both a and b
    r   Ú r   rC   )r$   rD   r2   rl   r   r.   Úravelrm   )r³   r´   Ú	operationÚavÚbvs        r<   Úboolean_rowsr»   _  s¹   € ô, 	�‰�aœrŸx™xÔ(€AÜ
�‰�aœrŸx™xÔ(€Aà	
�‰�"�a—g‘g�� !§'¡'¨!¡*Ñ,Ó	-×	3Ñ	3Ó	5€BØ	
�‰�"�a—g‘g�� !§'¡'¨!¡*Ñ,Ó	-×	3Ñ	3Ó	5€BÙ�R˜Ó×!Ñ! !§'¡'Ó*×2Ñ2°2°q·w±w¸q±zÓBÐBr>   c                 ó
  — t        j                  | t         j                  ¬«      } t        |«      }|rt	        j
                  | «      } t	        j                  | «      }t        ||«      \  }}t	        j                  |«      }||fS )a÷  
    Group vectors based on an angle tolerance, with the option to
    include negative vectors.

    Parameters
    -----------
    vectors : (n,3) float
        Direction vector
    angle : float
        Group vectors closer than this angle in radians
    include_negative : bool
        If True consider the same:
        [0,0,1] and [0,0,-1]

    Returns
    ------------
    new_vectors : (m,3) float
        Direction vector
    groups : (m,) sequence of int
        Indices of source vectors
    r   )	r$   rD   r~   Úfloatr   Úvector_hemisphereÚvector_to_sphericalÚgroup_distanceÚspherical_to_vector)ÚvectorsÚangleÚinclude_negativeÚ	sphericalÚanglesrT   Únew_vectorss          r<   Úgroup_vectorsrÈ   }  so   € ô. �m‰m˜G¬2¯:©:Ô6€GÜ�%‹L€EáÜ×(Ñ(¨Ó1ˆä×(Ñ(¨Ó1€IÜ# I¨uÓ5�N€FˆFÜ×*Ñ*¨6Ó2€KØ˜ÐÐr>   Údistancec                 ó  — t        j                  | t         j                  ¬«      } t        j                  t	        | «      t
        ¬«      }t        | «      }g }g }t        | «      D ]ˆ  \  }}||   rŒt        j                  |j                  ||«      t         j                  ¬«      }|||       }d||<   |j                  t        j                  | |   d¬«      «       |j                  |«       ŒŠ t        j                  |«      |fS )a»  
    Find non-overlapping groups of points where no two points in a
    group are farther than 2*distance apart.

    Parameters
    ---------
    values : (n, d) float
        Points of dimension d
    distance : float
        Max distance between points in a cluster

    Returns
    ----------
    unique : (m, d) float
        Median value of each group
    groups : (m) sequence of int
        Indexes of points that make up a group

    r   Tr   r¢   )r$   rD   r~   r%   r   r&   r   rg   r_   Úquery_ball_pointr2   r,   Úmedian)	rL   rÉ   ÚconsumedÚtreer‡   rT   rˆ   r§   rU   s	            r<   rÀ   rÀ      sÖ   € ô, �]‰]˜6¬¯©Ô4€Fä�x‰xœ˜F›¬4Ô0€HÜ�6‹?€Dð €Fà€Fä! &Ö)‰ˆˆuØ�EŠ?ØÜ—‘˜×.Ñ.¨u°hÓ?ÄrÇxÁxÔPˆØ�x ‘Ð&Ñ'ˆØˆ�‰Ø�‰”b—i‘i  u¡°AÔ6Ô7Ø�‰�eÕð *ô �8‰8�FÓ˜VÐ#Ð#r>   c                 óp   — ddl m} t        | «      }|j                  |d¬«      }|j	                  |«      }|S )aJ  
    Find clusters of points which have neighbours closer than radius

    Parameters
    ---------
    points : (n, d) float
        Points of dimension d
    radius : float
        Max distance between points in a cluster

    Returns
    ----------
    groups : (m,) sequence of int
        Indices of points in a cluster

    r   )ÚgraphÚndarray)ÚrÚoutput_type)r¶   rÐ   r   Úquery_pairsÚconnected_components)ÚpointsÚradiusrÐ   rÎ   ÚpairsrT   s         r<   ÚclustersrÙ   Ë  s<   € õ" ä�6‹?€Dð ×Ñ˜v°9ÐÓ=€Eà×'Ñ'¨Ó.€Fà€Mr>   r   c           	      óŒ  — t        | |¬«      } t        j                  t        | «      «      }d|j                  d<   |dd | dd | dd k7     }t        j
                  t        |«      dz   t        ¬«      }t        | «      |d<   ||dd |dd |dd z
  }	t        j                  |	|k\  |	|k  «      }
|rt        j                  |
| |dd    «      }
t        |
«      D ��cg c]  \  }}|sŒ	|||   ||dz       ‘Œ }}}|�rD| d	   | d   k7  r|S |rt        | d	   «      s|S t        |«      dk(  rt        |d	   «      t        | «      k(  r|S t        |«      d	kD  xr |d	   d	   d	k(  }t        |«      d	kD  xr |d   d   t        | «      dz
  k(  }|r3|r1t        j                  |d   |d	   «      |d	<   |j                  «        |S |	d	   |	d   z   }||k  s||kD  r|S t        j                  t        j                  |d
   |d   «      t        j                  |d	   |d   «      «      }|r||d	<   |S |r||d<   |S |j                  |«       |S c c}}w )aZ  
    Find the indices in an array of contiguous blocks
    of equal values.

    Parameters
    ------------
    data : (n,) array
      Data to find blocks on
    min_len : int
      The minimum length group to be returned
    max_len : int
      The maximum length group to be retuurned
    wrap : bool
      Combine blocks on both ends of 1D array
    digits : None or int
      If dealing with floats how many digits to consider
    only_nonzero : bool
      Only return blocks of non- zero values

    Returns
    ---------
    blocks : (m) sequence of (*,) int
      Indices referencing data
    r[   Fr^   r   NrC   r   r   r   éþÿÿÿ)ra   r$   r­   r   rn   r%   rb   Úlogical_andrg   r&   r,   Úpop)rV   r?   r@   ÚwraprW   Úonly_nonzeror­   r4   ÚinflÚinfl_lenÚinfl_okr;   ÚokÚblocksÚfirstÚlastÚcombinedÚ	new_blocks                     r<   rä   rä   è  s€  € ô2 ˜ VÔ,€Dô �Y‰Y”s˜4“yÓ!€FØ %€F‡L�L�Ñà�Q�Rˆj˜˜a˜b˜ T¨#¨2 YÑ.Ñ/€GÜ�8‰8”C˜“L 1Ñ$¬CÔ0€DÜ�4‹y€Dˆ�HØ€Dˆˆ2€Jð �A�Bˆx˜$˜s ˜)Ñ#€Hô �n‰n˜X¨Ñ0°(¸gÑ2EÓF€Gáô —.‘. ¨$¨t°C°R¨y©/Ó:ˆô :CÀ7Ô9KÔRÑ9K±°°2Êrˆf�T˜!‘W˜t A¨¡E™{Ò+Ð9K€FÑRâà�‰7�d˜2‘hÒØˆMñ ¤ T¨!¡W¤ØˆMô ˆv‹;˜!Ò¤ F¨1¡I£´#°d³)Ò ;ØˆMô �F“˜a‘Ò5 F¨1¡I¨a¡L°AÑ$5ˆä�6‹{˜Q‰ÒD 6¨"¡:¨b¡>´c¸$³iÀ!±mÑ#Dˆñ ‘TÜŸ	™	 &¨¡*¨f°Q©iÓ8ˆF�1‰IØ�J‰JŒLð. €Mð)   ‘{ X¨b¡\Ñ1ˆHà˜'Ò! X°Ò%7Ø�äŸ	™	Ü—	‘	˜$˜r™( D¨¡HÓ-¬r¯y©y¸¸a¹À$ÀqÁ'Ó/JóˆIñ à%��q‘	ð €Mñ à&��r‘
ð €Mð —‘˜iÔ(à€Mùóg Ss   Ã
I Ã$I c                 ó²   — t        j                  || f«      }| |   } ||   }t        j                  t        | «      d«      }d|d<   | dd | dd k7  |dd ||   S )a{  
    Given a list of groups find the minimum element of data
    within each group

    Parameters
    -----------
    groups : (n,) sequence of (q,) int
        Indexes of each group corresponding to each element in data
    data : (m,)
        The data that groups indexes reference

    Returns
    -----------
    minimums : (n,)
        Minimum value of data per group

    r&   Tr   r   NrC   )r$   Úlexsortr%   r   )rT   rV   rN   rˆ   s       r<   Ú	group_minrë   N  sk   € ô& �J‰J˜˜f�~Ó&€EØ�E‰]€FØ�‰;€Dä�H‰H”S˜“[ &Ó)€EØ€Eˆ!�HØ�q�r�
˜f S b˜kÑ)€Eˆ!ˆ"€IØ�‰;Ðr>   )NNNNN)NN)NT)N)FF)r   FF)FFN)NF)g-Cëâ6?F)+Ú__doc__Únumpyr$   r¶   r   Ú	constantsr   r   Útypedr   r   r	   r
   r   Úscipy.spatialr   ÚBaseExceptionÚEr   ÚExceptionWrapperr&   r=   rU   ry   r2   ra   r‰   r–   r™   r�   r3   rª   r²   Úintersect1dr»   rÈ   r›   r~   rÀ   rÙ   Úinfrä   rë   © r>   r<   Ú<module>r÷      sf  ðñó å ß ß @Õ @ð-Ý%ð "Ø"Ø$(Ø"&Ø $ñV5à�d‰{ðV5ð �t‘ðV5ð ˜T‘>ð	V5ð
 ˜4‘ðV5ð ˜‰~óV5ñr6˜7 T™>ð 6¸7ÀT¹>ó 6ðt GKñ?Ø
ð?Ø$ t™^ð?Ø?Cð?àó?ñD&A˜w¨™~ð &A¸ÀÇÁÑ9Jó &AðT INñ)Ø
ð)Ø#'ð)ØAEó)ð\ Ø Øñ	DØðDàðDð ðDð ó	DñN#�Yð #¨°$©ó #ðP Ø Ø!ñ	àðð ðð �d‰Nó	ó8GóD4ón9ðz +-¯.©.ñCØðCØðCàˆR�X‰XÑóCó< ðF($Øð($Ø!'ð($à
ˆ7�2—:‘:Ñ Ð(Ñ)ó($òVð:  B§F¡F°¸tÐRWó cóLøð} ò -õ à)ˆj×)Ñ)¨!Ó,†Gûð-ús   ¤D( Ä(EÄ-EÅE