
    OgR                        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               Z/var/www/html/public_html/myphp/venv/lib/python3.12/site-packages/ezdxf/math/clustering.pyr   r      s    0 A~233}fm,"$HFI
i.w' $i
IE229fEFI9~
*KK	"i(I**955D $i i. *22gD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   sU    3>t3DY 	+E))%0EB##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`   si     &oo/ 	AN((>*S-@@@	Ax=1}}VQ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"    HHJ(,,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:Rx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
 	
 ,4FMM&!4L+MH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   |   se     ?? $	
 	
#00!<	
 A JJqM	
	
 	
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      s1     ??7?@G	G	$Q	'@ @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 -3b 352#2# 2#,/2#2#j	r6   