
    'jR                        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dS )#    )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_sizepointslist[AnyVec]radiusfloatr   intr   Optional[RTree]r   returnlist[list[AnyVec]]c               z   |dk     rt          d          |t          | |          }g }t          |           }t          |          r|                                }|h}|h}	|                    |	           t          |          r|                                }
t          |                    |
|                    }t          |          |k     rZ|	                    |
           |                    |
           ||	                    |          z  }t          |          t          |          d |D             S )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 >= 2Nc                ,    g | ]}t          |          S  )list.0clusters     O/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/math/clustering.py
<listcomp>zdbscan.<locals>.<listcomp>D   s    222gDMM222    )

ValueErrorr   setlenpopappendpoints_in_sphereadddiscardintersection)r   r   r   r   r   clusters	point_setpointtodor%   	chk_point	neighborss               r&   r   r      s;   0 A~~2333}fm,,"$HFI
i.. 6w'   $ii 	6

IE229fEEFFI9~~
**KK	"""i(((I**9555D $ii 	6 i.. 6 322222r(   
   kmax_iterc                h    d
 fd}d fd}d }dcxk     rt                     k     sn t          d	           |t          j                             t	          |          D ]%} | |                      } ||          r n|&t                                                    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

    	centroidsIterable[AnyVec]c                    t          t                    }t          |           }D ]5}|                    |          \  }}||                             |           6|S N)r   r"   r   nearest_neighborr-   )r<   new_clusterstreer4   nn_r   s         r&   classifyzk_means.<locals>.classifyX   se    3>t3D3DY 	+ 	+E))%00EB##E****r(   r   Iterator[AnyVec]c               3    K                                    D ](} t          j        |           t          |           z  V  )t                    k     r-t	          j        t                    z
            E d {V  d S d S r?   )valuesr
   sumr+   randomsample)cluster_pointsr2   r9   r   s    r&   recenterzk_means.<locals>.recenter`   s      &oo// 	A 	AN(>**S-@-@@@@@@x==1}VQX->??????????? r(   c                    d }t          t          ||                                                     }t          t          ||                                                    }||k    S )Nc                    |                                   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)    HHJJJ(,D#777r(   )sortedrS   rH   )old_clustersrA   rV   h1h2s        r&   is_equal_clusteringz$k_means.<locals>.is_equal_clusteringf   sb    	8 	8 	8 C	<#6#6#8#899::C	<#6#6#8#899::Rxr(      z7invalid argument k: must be in range [2, len(points)-1])r<   r=   )r   rF   )r+   r)   rJ   rK   ranger"   rH   )	r   r9   r:   rE   rM   r[   rD   rA   r2   s	   ``      @r&   r   r   G   s   "     @ @ @ @ @ @ @ @   CKKE
 
 	
 ,48FM&!4L4L+M+MH8__    x

++x66 	E!!"""r(   r2   c                >    t          j        d | D                       S )z:Returns the average point-to-point intra cluster distance.c                n    g | ]2}t          j        |d           D ]\  }}|                    |          3S )r   )	itertoolscombinationsdistance)r$   r%   pqs       r&   r'   z2average_intra_cluster_distance.<locals>.<listcomp>   sZ     	
 	
 	
#0!<<	
 	
 A JJqMM	
 	
 	
 	
r(   
statisticsmeanr2   s    r&   r   r   |   s4     ?	
 	
#	
 	
 	
  r(   c                >    t          j        d | D                       S )z#Returns the average cluster radius.c                8    g | ]}t          |          d          S )r\   )r   r#   s     r&   r'   z*average_cluster_radius.<locals>.<listcomp>   s&    @@@G	G	$	$Q	'@@@r(   re   rh   s    r&   r   r      s)     ?@@x@@@  r(   )r   r   r   r   r   r   r   r   r   r   r   r   )r8   )r   r   r9   r   r:   r   r   r   )r2   r   r   r   )
__future__r   typingr   r   r   rJ   rf   r`   rQ   collectionsr   	functoolsr   
ezdxf.mathr	   r
   r   ezdxf.math.rtreer   __all__r   r   r   r   r!   r(   r&   <module>rr      sA   # " " " " " / / / / / / / / / /           # # # # # #       7 7 7 7 7 7 7 7 7 7 " " " " " "   !-3 -3 -3 -3 -3 -3b 352# 2# 2# 2# 2#j	 	 	 	     r(   