
    Ogu<                       d dl mZ d dlmZmZmZ d dlmZ d dlZd dl	m
Z
 d dlmZ d dlmZmZmZmZmZ d dlmZ d d	lmZmZ d d
lmZ g dZ G d dej4                        Z G d de      Z G d de      Z G d de      Zdd	 	 	 	 	 	 	 ddZdd	 	 	 	 	 	 	 ddZ dd	 	 	 	 	 	 	 ddZ!	 d	 	 	 	 	 	 	 d dZ"dd	 	 	 	 	 	 	 d!dZ#dd	 	 	 	 	 	 	 d"dZ$dd	 	 	 	 	 	 	 d#dZ% G d d      Z&y)$    )annotations)IterableCallableSequence)overrideN)bbox)	DXFEntity)UVecVec2Vec3BoundingBox2dis_point_in_polygon_2d)CohenSutherlandLineClipping2d)rtreeBoundingBox)EntityQuery)
bbox_chainedbbox_crosses_fencebbox_insidebbox_outsidebbox_overlapCirclePlanarSearchIndexpoint_in_bboxPolygonWindowc                      e Zd ZdZej
                  dd       Zej
                  dd       Zej
                  dd       Zy)SelectionShapezvAbstractBaseClass for selection shapes.

    It is guaranteed that all methods get an entity_bbox which has data!
    c                     y N selfentity_bboxs     Q/var/www/html/public_html/myphp/venv/lib/python3.12/site-packages/ezdxf/select.pyis_inside_bboxzSelectionShape.is_inside_bbox$   s    BE    c                     y r    r!   r"   s     r%   is_outside_bboxzSelectionShape.is_outside_bbox'   s    CFr'   c                     y r    r!   r"   s     r%   is_overlapping_bboxz"SelectionShape.is_overlapping_bbox*   s    GJr'   Nr$   r   returnbool)	__name__
__module____qualname____doc__abcabstractmethodr&   r)   r+   r!   r'   r%   r   r      sE    
 	E EF FJ Jr'   r   c                  N    e Zd ZdZddZedd       Zedd       Zedd       Zy)	r   zThis selection shape tests entities against a rectangular and axis-aligned 2D
    window.  All entities are projected on the xy-plane.

    Args:
        p1: first corner of the window
        p2: second corner of the window
    c                (    t        ||f      | _        y r    )r   _bbox)r#   p1p2s      r%   __init__zWindow.__init__7   s    "B8,
r'   c                8    | j                   j                  |      S r    )r7   containsr"   s     r%   r&   zWindow.is_inside_bbox:   s    zz"";//r'   c                :    | j                   j                  |       S r    r7   has_overlapr"   s     r%   r)   zWindow.is_outside_bbox>   s    ::))+666r'   c                8    | j                   j                  |      S r    r>   r"   s     r%   r+   zWindow.is_overlapping_bboxB   s    zz%%k22r'   N)r8   r
   r9   r
   r,   )	r/   r0   r1   r2   r:   r   r&   r)   r+   r!   r'   r%   r   r   .   sH    - 0 0 7 7 3 3r'   r   c                  V    e Zd ZdZddZd	dZed
d       Zed
d       Zed
d       Z	y)r   zThis selection shape tests entities against a circle.  All entities are
    projected on the xy-plane.

    Args:
        center: center of the circle
        radius: radius of the circle
    c                    t        |      | _        t        |      | _        t        | j                  | j                        }t	        | j                  |z
  | j                  |z   f      | _        y r    )r   _centerfloat_radiusr   r7   )r#   centerradiusr_vecs       r%   r:   zCircle.__init__P   sO    F|V}T\\4<<0"DLL5$8$,,:N#OP
r'   c                R    | j                   j                  |      | j                  k  S r    )rC   distancerE   )r#   vs     r%   _is_vertex_insidezCircle._is_vertex_insideV   s     ||$$Q'4<<77r'   c                H     t         fd|j                         D              S )Nc              3  @   K   | ]  }j                  |        y wr    rL   .0rK   r#   s     r%   	<genexpr>z(Circle.is_inside_bbox.<locals>.<genexpr>[   s     R4))!,R   )allrect_verticesr"   s   ` r%   r&   zCircle.is_inside_bboxY   s    Rk6O6O6QRRRr'   c                &    | j                  |       S r    r+   r"   s     r%   r)   zCircle.is_outside_bbox]       ++K888r'   c                      j                   j                  |      syt         fd|j                         D              ry j	                  |j
                        S )NFc              3  @   K   | ]  }j                  |        y wr    rO   rP   s     r%   rR   z-Circle.is_overlapping_bbox.<locals>.<genexpr>e   s     NQt%%a(NrS   T)r7   r?   anyrU   rL   rF   r"   s   ` r%   r+   zCircle.is_overlapping_bboxa   sI    zz%%k2N+2K2K2MNN%%k&8&899r'   N)rF   r
   rG   rD   )rK   r   r-   r.   r,   )
r/   r0   r1   r2   r:   rL   r   r&   r)   r+   r!   r'   r%   r   r   G   sP    Q8 S S 9 9 : :r'   r   c                  V    e Zd ZdZddZd	dZed
d       Zed
d       Zed
d       Z	y)r   zThis selection shape tests entities against an arbitrary closed polygon.
    All entities are projected on the xy-plane. Complex **concave** polygons may not
    work as expected.
    c                "   t        j                  |      }t        |      dk  rt        d      |d   j	                  |d         r|j                          t        |      dk  rt        d      || _        t        | j                        | _        y )N   z3 or more vertices requiredr   )	r   listlen
ValueErrorisclosepop	_verticesr   r7   )r#   verticesrK   s      r%   r:   zPolygon.__init__p   sr    IIhq6A::;;Q4<<"EEGq6A::;;%&"4>>2
r'   c                    t        ||      }| j                  }t        |      D ]  \  }}|j                  ||dz
     |      s y y)N   TF)r   re   	enumerate	clip_line)r#   extminextmaxcsrf   indexends          r%   _has_intersectionzPolygon._has_intersection{   sN    *66:>>#H- 	JE3||HUQY/5	 r'   c                
     j                   j                  |      syt         fd|j                         D              ry|j                  \  |j
                  \  t        fd j                  D               S )NFc              3  P   K   | ]  }t        |j                        d k    ywr   Nr   re   rP   s     r%   rR   z)Polygon.is_inside_bbox.<locals>.<genexpr>   s)      
 #1dnn59
   #&c              3     K   | ]:  }|j                   cxk  xr k  nc xr |j                  cxk  xr k  nc  < y wr    )xy)rQ   rK   max_xmax_ymin_xmin_ys     r%   rR   z)Polygon.is_inside_bbox.<locals>.<genexpr>   s:      
@AUQSS 5 ;uqss':U':;
s   A A)r7   r?   r[   rU   rk   rl   re   )r#   r$   ry   rz   r{   r|   s   ` @@@@r%   r&   zPolygon.is_inside_bbox   s~    zz%%k2 
 ..0
 
  #))u"))u 
EI^^
 
 
 	
r'   c                &    | j                  |       S r    rW   r"   s     r%   r)   zPolygon.is_outside_bbox   rX   r'   c                      j                   j                  |      syt         fd|j                         D              ry j	                  |j
                  |j                        S )NFc              3  P   K   | ]  }t        |j                        d k\    ywrs   rt   rP   s     r%   rR   z.Polygon.is_overlapping_bbox.<locals>.<genexpr>   s)      
 #1dnn5:
ru   T)r7   r?   r[   rU   rp   rk   rl   r"   s   ` r%   r+   zPolygon.is_overlapping_bbox   s\    zz%%k2 
 ..0
 
  %%k&8&8+:L:LMMr'   N)rf   Iterable[UVec])rk   r   rl   r   r-   r.   r,   )
r/   r0   r1   r2   r:   rp   r   r&   r)   r+   r!   r'   r%   r   r   j   sO    
	3 
 
$ 9 9 
N 
Nr'   r   )cachec               0    t        || j                  |      S )zSelects entities whose bounding box lies withing the selection shape.

    Args:
        shape: seclection shape
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    )select_by_bboxr&   shapeentitiesr   s      r%   r   r      s     (E$8$8%@@r'   c               0    t        || j                  |      S )zSelects entities whose bounding box is completely outside the selection shape.

    Args:
        shape: seclection shape
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    )r   r)   r   s      r%   r   r      s     (E$9$95AAr'   c               0    t        || j                  |      S )zSelects entities whose bounding box overlaps the selection shape.

    Args:
        shape: seclection shape
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    )r   r+   r   s      r%   r   r      s     (E$=$=uEEr'   c                    g }| D ]K  }t        j                  |fd|      }|j                  s) |t        |            s;|j	                  |       M t        |      S )a  Calculates the bounding box for each entity and returns all entities for that the
    test function returns ``True``.

    Args:
        entities: iterable of DXFEntities
        func: test function which takes the bounding box of the entity as input and
            returns ``True`` if the entity is part of the selection.
        cache: optional :class:`ezdxf.bbox.Cache` instance

    Tfastr   )r   extentshas_datar   appendr   )r   	test_funcr   	selectionentityr   s         r%   r   r      s`     "$I %,,yt5A]7+,V$% y!!r'   c                   dfd}t        j                  |       t              dk  rt        d      t	              t        |||      S )ag  Selects entities whose bounding box intersects an open polyline.

    All entities are projected on the xy-plane.

    A single point can not be selected by a fence polyline by definition.

    Args:
        vertices: vertices of the selection polyline
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    c           	         j                         syt         fdD              ry j                  } j                  }|j	                  |      ryt        ||      t        fdt        dd        D              S )NFc              3  @   K   | ]  }j                  |        y wr    inside)rQ   rK   r$   s     r%   rR   z:bbox_crosses_fence.<locals>.is_crossing.<locals>.<genexpr>  s     8{!!!$8rS   Tc              3  H   K   | ]  \  }}j                  ||        y wr    )rj   )rQ   startro   rm   s      r%   rR   z:bbox_crosses_fence.<locals>.is_crossing.<locals>.<genexpr>  s%      
)3BLL$
s   "rh   )r?   r[   rk   rl   rc   r   zip)r$   rk   rl   rm   r7   re   s   `  @r%   is_crossingz'bbox_crosses_fence.<locals>.is_crossing  s      -8i88 ####>>&!*66: 
7:9iPQPRm7T
 
 	
r'      z2 or more vertices requiredr,   )r   r`   ra   rb   r   r   )rf   r   r   r   r7   re   s       @@r%   r   r      sI    &
  		(#I
9~677)$E(K77r'   c               @    dfd}t        |       t        |||      S )a  Selects entities where the selection point lies within the bounding box.
    All entities are projected on the xy-plane.

    Args:
        point: selection point
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    c                &    | j                        S r    r   )r$   points    r%   r   z"point_in_bbox.<locals>.is_crossing-  s    !!%((r'   r,   )r   r   )locationr   r   r   r   s       @r%   r   r      s"    ) NE(K77r'   c               0   dfd}t        j                         |  ||       i}t        |      }d}|rHd}|D ]>  }||v r ||      }|j                         D ]  }|j	                  |      s|||<   d} > @ |rHt        |j                               S )u  Selects elements that are directly or indirectly connected to each other by
    overlapping bounding boxes. The selection begins at the specified starting element.

    Warning: the current implementation has a complexity of O(n²).

    Args:
        start: first entity of selection
        entities: iterable of DXFEntities
        cache: optional :class:`ezdxf.bbox.Cache` instance

    c                H    t        t        j                  | fd            S )NTr   )r   r   r   )r   r   s    r%   get_bbox_2dz!bbox_chained.<locals>.get_bbox_2dC  s    T\\6)$eLMMr'   TF)r   r	   r-   r   )r   Cacher`   valuesr?   r   keys)	r   r   r   r   selectedrestartr   r$   selected_bboxs	     `      r%   r   r   4  s    N }

05{57I/JHH~HG
 	F!%f-K!)!2 **=9'2HV$"G			  x}}''r'   c                  H    e Zd ZdZ	 	 d	 	 	 ddZd	dZ	 	 	 	 	 	 d
dZddZy)r   a  **Spatial Search Index for DXF Entities**

    This class implements a spatial search index for DXF entities based on their
    bounding boxes except for POINT and LINE.
    It operates strictly within the two-dimensional (2D) space of the xy-plane.
    The index is built once and cannot be extended afterward.

    The index can be used to pre-select DXF entities from a certain area to reduce the
    search space for other selection tools of this module.

    **Functionality**

    - The index relies on the bounding boxes of DXF entities, and only the corner
      vertices of these bounding boxes are indexed except for POINT and LINE.
    - It can only find DXF entities that have at least one bounding box vertex located
      within the search area. Entities whose bounding boxes overlap the search area but
      have no vertices inside it will not be found (e.g., a circle whose center point
      is inside the search area but none of its bounding box vertices will not be
      included).
    - The detection behavior can be customized by overriding the :meth:`detection_points`
      method.

    **Recommendations**

    Since this index is intended to be used in conjunction with other selection tools
    within this module, it's recommended to maintain a bounding box cache to avoid
    the computational cost of recalculating them frequently. This class creates a new
    bounding box cache if none is specified. This cache can be accessed through the
    public attribute :attr:`cache`.

    Nc           	     ~  	  G d dt               dfd|xs t        j                         | _        i | _        g }|D ]K  }| j                  |      }|st        |      	|| j                  	<   |j                  	fd|D               M t        j                  |t        dt        |                  | _        y )Nc                      e Zd ZdZy),PlanarSearchIndex.__init__.<locals>.RTreeVtxuidN)r/   r0   r1   	__slots__r!   r'   r%   RTreeVtxr     s     Ir'   r   c                &     |       }||_         |S r    r   )r   r   vertexr   s      r%   detection_vertexz4PlanarSearchIndex.__init__.<locals>.detection_vertex  s    h'FFJMr'   c              3  0   K   | ]  } |        y wr    r!   )rQ   pntr   r   s     r%   rR   z-PlanarSearchIndex.__init__.<locals>.<genexpr>  s      &/2 c*&s      )max_node_size)r   r   r   intr-   r   )r   r   r   r   	_entitiesdetection_pointsidextendr   RTreemaxr   _search_tree)
r#   r   r   r   detection_verticesr   r   r   r   r   s
          @@@r%   r:   zPlanarSearchIndex.__init__|  s    	!t 	!	
 *djjl
/1-/ 		F#44V<#V*C"(DNN3%% &6F& 		 "KKc!S5G.H
r'   c                   |j                         }|dk(  r t        |j                  j                        fS |dk(  r>t        |j                  j                        t        |j                  j
                        fS t        t        j                  |fd| j                              }|j                  r|j                         S t               S )a  Returns the detection points for a given DXF entity.

        The detection points must be 2D points projected onto the xy-plane (ignore z-axis).
        This implementation returns the corner vertices of the entity bounding box.

        Override this method to return more sophisticated detection points
        (e.g., the vertices of LWPOLYLINE and POLYLINE or equally spaced raster points
        for block references).
        POINTLINETr   )dxftyper   dxfr   r   ro   r   r   r   r   r   rU   tuple)r#   r   r   box2ds       r%   r   z"PlanarSearchIndex.detection_points  s     .."g,,-//f))*D,@AAdllF94tzzRS>>&&((wr'   c                    | j                   j                  t        |      |      }| j                  }t	        d |D              D cg c]  }||   	 c}S c c}w )zReturns all DXF entities that have at least one detection point located
        around `center` with a max. distance of `radius`.
        c              3  4   K   | ]  }|j                     y wr    r   rQ   rK   s     r%   rR   z>PlanarSearchIndex.detection_point_in_circle.<locals>.<genexpr>       ,OqQUU,O   )r   points_in_spherer   r   set)r#   rF   rG   r   r   r   s         r%   detection_point_in_circlez+PlanarSearchIndex.detection_point_in_circle  sN     "..??VfU>>),,O<N,O)OP#PPPs   Ac                    | j                   j                  t        t        |      t        |      g            }| j                  }t        d |D              D cg c]  }||   	 c}S c c}w )zReturns all DXF entities that have at least one detection point located
        inside or at the border of the rectangle defined by the two given corner points.
        c              3  4   K   | ]  }|j                     y wr    r   r   s     r%   rR   z<PlanarSearchIndex.detection_point_in_rect.<locals>.<genexpr>  r   r   )r   points_in_bboxr   r   r   r   )r#   r8   r9   r   r   r   s         r%   detection_point_in_rectz)PlanarSearchIndex.detection_point_in_rect  s_     "..==b48,-
 >>),,O<N,O)OP#PPPs   A()Nr   )r   Iterable[DXFEntity]r   bbox.Cache | None)r   r	   r-   zSequence[Vec2])rF   r
   rG   rD   r-   Sequence[DXFEntity])r8   r
   r9   r
   r-   r   )r/   r0   r1   r2   r:   r   r   r   r!   r'   r%   r   r   [  sS    F $(	
%
 !
>*QQ$)Q	QQr'   r   )r   r   r   r   r   r   r-   r   r    )r   r   r   zCallable[[BoundingBox2d], bool]r   r   r-   r   )rf   r   r   r   r   r   r-   r   )r   r
   r   r   r   r   r-   r   )r   r	   r   r   r   r   r-   r   )'
__future__r   typingr   r   r   typing_extensionsr   r3   ezdxfr   ezdxf.entitiesr	   
ezdxf.mathr
   r   r   r   r   ezdxf.math.clippingr   r   r   ezdxf.queryr   __all__ABCr   r   r   r   r   r   r   r   r   r   r   r   r!   r'   r%   <module>r      s   # / / & 
  $ N N = ) #KSWW K 3^ 32 :^  :F;Nn ;ND  $	AA!A 	A
 A*  $	BB!B 	B
 B*  $	FF!F 	F
 F(  $"!"." " 	"<  $	(8(8!(8 	(8
 (8X RV8818=N88* TX$($( 3$(?P$($(NgQ gQr'   