Ë
    £èhß  ã                  óÖ   — d dl mZ d dlmZmZmZ d dlZd dlZd dlZd dl	Z	d dl
mZ d dlmZ d dlmZmZmZ d dlmZ g d¢Zd	dd
dœ	 	 	 	 	 	 	 	 	 	 	 dd„Z	 d	 	 	 	 	 	 	 dd„Zdd„Zdd„Zy)é    )Úannotations)ÚIteratorÚIterableÚOptionalN)Údefaultdict)Úreduce)ÚAnyVecÚVec3Úspherical_envelope)ÚRTree)ÚdbscanÚk_meansÚaverage_cluster_radiusÚaverage_intra_cluster_distanceé   é   )Ú
min_pointsÚrtreeÚmax_node_sizec               ó  — |dk  rt        d«      ‚|€t        | |«      }g }t        | «      }t        |«      rº|j	                  «       }|h}|h}	|j                  |	«       t        |«      r||j	                  «       }
t        |j                  |
|«      «      }t        |«      |k  rŒE|	j                  |
«       |j                  |
«       ||j                  |«      z  }t        |«      rŒ|t        |«      rŒº|D �	cg c]  }	t        |	«      ‘Œ c}	S c c}	w )aó  DBSCAN clustering.

    https://en.wikipedia.org/wiki/DBSCAN

    Args:
        points: list of points to cluster
        radius: radius of the dense regions
        min_points: minimum number of points that needs to be within the
            `radius` for a point to be a core point (must be >= 2)
        rtree: optional :class:`~ezdxf.math.rtree.RTree`
        max_node_size: max node size for internally created RTree

    Returns:
        list of clusters, each cluster is a list of points

    é   zmin_points must be >= 2)Ú
ValueErrorr   ÚsetÚlenÚpopÚappendÚpoints_in_sphereÚaddÚdiscardÚintersectionÚlist)ÚpointsÚradiusr   r   r   ÚclustersÚ	point_setÚpointÚtodoÚclusterÚ	chk_pointÚ	neighborss               ú5lib/python3.12/site-packages/ezdxf/math/clustering.pyr   r      sù   € ð0 �A‚~ÜÐ2Ó3Ð3Ø€}Ü�f˜mÓ,ˆà"$€HÜ�F“€IÜ
ˆiŒ.Ø—‘“ˆØˆwˆØ�'ˆØ�‰˜Ô Ü�$ŒiØŸ™›
ˆIÜ˜E×2Ñ2°9¸fÓEÓFˆIÜ�9‹~ 
Ò*ØØ�K‰K˜	Ô"Ø×Ñ˜iÔ(Ø�I×*Ñ*¨9Ó5Ñ5ˆDô �$�iô ˆi�.ñ *2Ó2©˜gŒD��M¨Ñ2Ð2ùÒ2s   Ã5D
c                ó>  ‡ ‡‡— dˆ fd„}dˆˆˆ fd„}d„ }d‰cxk  rt        ‰ «      k  st        d«      ‚ t        d«      ‚ |t        j                  ‰ ‰«      «      Št	        |«      D ]  } | |«       «      } |‰|«      r n|ŠŒ t        ‰j                  «       «      S )a  K-means clustering.

    https://en.wikipedia.org/wiki/K-means_clustering

    Args:
        points: list of points to cluster
        k: number of clusters
        max_iter: max iterations

    Returns:
        list of clusters, each cluster is a list of points

    c                óš   •— t        t        «      }t        | «      }‰D ]*  }|j                  |«      \  }}||   j	                  |«       Œ, |S ©N)r   r!   r   Únearest_neighborr   )Ú	centroidsÚnew_clustersÚtreer&   ÚnnÚ_r"   s         €r+   Úclassifyzk_means.<locals>.classifyX   sP   ø€ Ü3>¼tÓ3DˆÜ�YÓˆÛˆEØ×)Ñ)¨%Ó0‰EˆB�Ø˜Ñ×#Ñ# EÕ*ð ð Ðó    c               3  óô   •K  — ‰j                  «       D ]%  } t        j                  | «      t        | «      z  –— Œ' t        ‰«      ‰k  r+t	        j
                  ‰‰t        ‰«      z
  «      E d {  –—†  y y 7 Œ­wr.   )Úvaluesr
   Úsumr   ÚrandomÚsample)Úcluster_pointsr$   Úkr"   s    €€€r+   Úrecenterzk_means.<locals>.recenter`   sb   øè ø€ Ø&Ÿo™oÖ/ˆNÜ—(‘(˜>Ó*¬S°Ó-@Ñ@Ó@ð 0äˆx‹=˜1ÒÜ—}‘} V¨Q´°X³Ñ->Ó?×?Ñ?ð Ø?ús   ƒA,A8Á/A6Á0A8c                óž   — d„ }t        t        || j                  «       «      «      }t        t        ||j                  «       «      «      }||k(  S )Nc                ór   — | j                  «        t        t        j                  t	        t
        | «      «      S r.   )Úsortr   ÚoperatorÚxorÚmapÚhash)Úlsts    r+   Ú	hash_listz7k_means.<locals>.is_equal_clustering.<locals>.hash_listg   s"   € Ø�H‰HŒJÜœ(Ÿ,™,¬¬D°#«Ó7Ð7r6   )ÚsortedrD   r8   )Úold_clustersr1   rG   Úh1Úh2s        r+   Úis_equal_clusteringz$k_means.<locals>.is_equal_clusteringf   sF   € ò	8ô ”C˜	 <×#6Ñ#6Ó#8Ó9Ó:ˆÜ”C˜	 <×#6Ñ#6Ó#8Ó9Ó:ˆØ�R‰xˆr6   é   z7invalid argument k: must be in range [2, len(points)-1])r0   zIterable[AnyVec])ÚreturnzIterator[AnyVec])r   r   r:   r;   Úranger!   r8   )	r"   r=   Úmax_iterr5   r>   rL   r4   r1   r$   s	   ``      @r+   r   r   G   s¢   ú€ õ"÷@òð �Ô”C˜“KÒÜØEó
ð 	
ð  ÜØEó
ð 	
ñ ,4´F·M±MÀ&È!Ó4LÓ+M€HÜ�8Ž_ˆÙ¡£
Ó+ˆÙ˜x¨Ô6ÙØ‰ð	 ô
 �—‘Ó!Ó"Ð"r6   c                ó¸   — t        j                  | D ���cg c]1  }t        j                  |d«      D ]  \  }}|j	                  |«      ‘Œ Œ3 c}}}«      S c c}}}w )z:Returns the average point-to-point intra cluster distance.r   )Ú
statisticsÚmeanÚ	itertoolsÚcombinationsÚdistance)r$   r(   ÚpÚqs       r+   r   r   |   s]   € ô �?‰?ñ $õ	
á#�Ü#×0Ñ0°¸!Ö<‘��Að �J‰J�q�Mà<ð Ø#ó	
óð ùô	
s   –6Ac                ój   — t        j                  | D �cg c]  }t        |«      d   ‘Œ c}«      S c c}w )z#Returns the average cluster radius.rM   )rR   rS   r   )r$   r(   s     r+   r   r   ˆ   s5   € ô �?‰?Ù7?Ó@±x¨GÔ	˜GÓ	$ QÓ	'°xÑ@óð ùÚ@s   ”0)r"   úlist[AnyVec]r#   Úfloatr   Úintr   zOptional[RTree]r   r\   rN   úlist[list[AnyVec]])é
   )r"   rZ   r=   r\   rP   r\   rN   r]   )r$   r]   rN   r[   )Ú
__future__r   Útypingr   r   r   r:   rR   rT   rB   Úcollectionsr   Ú	functoolsr   Ú
ezdxf.mathr	   r
   r   Úezdxf.math.rtreer   Ú__all__r   r   r   r   © r6   r+   Ú<module>rg      s²   ðõ #ß /Ñ /Û Û Û Û Ý #Ý ç 7Ñ 7Ý "ò€ð Ø!Øñ-3Øð-3ð ð-3ð ð	-3ð
 ð-3ð ð-3ð ó-3ðb 35ð2#Øð2#Ø ð2#Ø,/ð2#àó2#ój	ôr6   