
    hE                    j   S SK Jr  S SKJrJr  S SKrS SKJr  S SKJ	r	  S SK
Jr  S SKJrJrJrJrJr  S SKJrJrJrJrJrJr  S S	KJr  / S
QrSrSrSrSrSr \RB                   " S S5      5       r" " S S5      r#SS jr$      SS jr%SS jr&SS jr'S S jr(    S!S jr)        S"S jr*S#S jr+g)$    )annotations)IterableSequenceN)const)Tags)dxftag)SpatialFilter	DXFEntity
DictionaryInsertXRecord)Vec2Vec3UVecZ_AXISMatrix44BoundingBox2d)RoundtripXRecord)get_spatial_filterXClipClippingPathACAD_FILTERACAD_XREC_ROUNDTRIPACAD_INVERTEDCLIP_ROUNDTRIP#ACAD_INVERTEDCLIP_ROUNDTRIP_COMPARESPATIALc                      \ rS rSr% Sr\" 5       rS\S'   \" 5       rS\S'   \" 5       r	S\S'   Sr
S\S	'   SS
 jrSS jrSrg)r      a  Stores the SPATIAL_FILTER clipping paths in original form that I still don't fully
understand for `inverted` clipping paths. All boundary paths are simple polygons as a
sequence of :class:`~ezdxf.math.Vec2`.

Attributes:
    vertices: Contains the boundary polygon for regular clipping paths.
        Contains the outer boundary path for inverted clippings paths - but not always!
    inverted_clip:
        Contains the inner boundary for inverted clipping paths - but not always!
    inverted_clip_compare:
        Contains the combined inner- and the outer boundaries for inverted
        clipping paths - but not always!
    is_inverted_clip: ``True`` for inverted clipping paths

Sequence[Vec2]verticesinverted_clipinverted_clip_compareFboolis_inverted_clipc                    U R                   (       d  U R                  $ U R                  n[        U R                  5      [        U5      :  a  U R                  nU$ )z7Returns the inner clipping polygon as sequence of Vec2.)r$   r    	bbox_arear!   )selfinner_polygons     =/var/www/html/env/lib/python3.13/site-packages/ezdxf/xclip.pyr(   ClippingPath.inner_polygon/   sI     $$== T''(9]+CC ..M    c                x    U R                   (       d  [        U R                  5      $ [        U R                  5      $ )z-Returns the maximum extents as BoundingBox2d.)r$   r   r    r"   r'   s    r)   outer_boundsClippingPath.outer_bounds:   s-    $$ // T7788r+    Nreturnr   )r2   r   )__name__
__module____qualname____firstlineno____doc__tupler    __annotations__r!   r"   r$   r(   r.   __static_attributes__r0   r+   r)   r   r      sC       %wHn&$)GM>+,1G>3"d"	9r+   r   c                     \ rS rSrSrSS jrSS jrSS jr\SS j5       r	\SS j5       r
\SS j5       rSS	 jrSS
 jrSS jrSS jrSS jrSS jr S SS.   S!S jjjrS"S jr      S#S jrSS jrSS jrS rSrg)$r   C   aI  Helper class to manage the clipping path of INSERT entities.

Provides a similar functionality as the XCLIP command in CAD applications.

.. important::

    This class handles only 2D clipping paths.

The visibility of the clipping path can be set individually for each block
reference, but the HEADER variable $XCLIPFRAME ultimately determines whether the
clipping path is displayed or plotted by the application:

=== =============== ===
0   not displayed   not plotted
1   displayed       not plotted
2   displayed       plotted
=== =============== ===

The default setting is 2.

c                    [        U[        5      (       d"  [        R                  " S[	        U5       35      eXl        [        U5      U l        g )NzINSERT entity required, got )
isinstancer   r   DXFTypeErrorstr_insertr   _spatial_filter)r'   inserts     r)   __init__XClip.__init__Z   s>    &&))$$'CCK=%QRR1&9r+   c                    U R                   $ )zwReturns the underlaying SPATIAL_FILTER entity if the INSERT entity has a
clipping path and returns ``None`` otherwise.
rB   r-   s    r)   r   XClip.get_spatial_filter`   s     ###r+   c                    SnU R                   R                  b0  U R                   R                  R                  R                  SS5      nU$ )N   z$XCLIPFRAME)rA   docheaderget)r'   policys     r)   get_xclip_frame_policyXClip.get_xclip_frame_policyf   s>    <<'\\%%,,00BFr+   c                    U R                   SL$ )z1Returns if the INSERT entity has a clipping path.NrG   r-   s    r)   has_clipping_pathXClip.has_clipping_pathl   s     ##4//r+   c                    [        U R                  [        5      (       a)  [        U R                  R                  R
                  5      $ g)z8Returns ``True`` if block reference clipping is enabled.F)r>   rB   r	   r#   dxfis_clipping_enabledr-   s    r)   rV   XClip.is_clipping_enabledq   s7     d**M::,,00DDEEr+   c                ^    [        U R                  5      nUc  gUR                  [        5      $ )z.Returns ``True`` if clipping path is inverted.F)get_roundtrip_xrecordrB   has_sectionr   )r'   xrecs     r)   r$   XClip.is_inverted_clipx   s.     %T%9%9:< ;<<r+   c                z    [        U R                  [        5      (       a  SU R                  R                  l        gg)z Enable block reference clipping.   Nr>   rB   r	   rU   rV   r-   s    r)   enable_clippingXClip.enable_clipping   .    d**M::;<D  $$8 ;r+   c                z    [        U R                  [        5      (       a  SU R                  R                  l        gg)z!Disable block reference clipping.r   Nr_   r-   s    r)   disable_clippingXClip.disable_clipping   rb   r+   c                   / n[        U R                  [        5      (       d
  [        5       $ U R                  R                  n[
        R                  " UR                  U R                  R                  5      5      n[        U5      S:X  a  [        U5      n[        USS9n[        U R                  5      n[        U[        5      (       a3  [        U[        U5      Ul        [        U[         U5      Ul        SUl        U$ )zNReturns the clipping path in block coordinates (relative to the block origin).rJ   Fr$   T)r>   rB   r	   r   inverse_insert_matrixr   r8   transform_verticesboundary_verticeslen
_rect_pathrY   r   get_roundtrip_verticesr   r!   r   r"   r$   )r'   r    mclipping_pathr[   s        r)   get_block_clipping_pathXClip.get_block_clipping_path   s    #%$..>>>!  66::  !5!5!G!GH
 x=A!(+H$XF$T%9%9:d,--*@11+M' 3I913M/ .2M*r+   c                   [        5       n[        U R                  [        5      (       d  [	        X5      $ U R                  5       nU R                  R                  5       n[        R                   " UR                  UR                  5      5      n[        U5      S:X  a  [        U5      R                  5       n[	        XR                  S9nUR                  (       a  [        R                   " UR                  UR                  5      5      n[        U5      S:X  a  [        U5      R                  5       nXTl        [        R                   " UR                  UR                   5      5      Ul        U$ )zrReturns the clipping path in WCS coordinates (relative to the WCS origin) as
2D path projected onto the xy-plane.
rJ   rg   )r8   r>   rB   r	   r   rp   rA   matrix44r   ri   r    rk   r   rect_verticesr$   r!   r"   )r'   r    block_clipping_pathrn   wcs_clipping_pathr!   s         r)   get_wcs_clipping_pathXClip.get_wcs_clipping_path   s"    $)7$..>>33"::<LL!!#::a223F3O3OPQx=A$X.<<>H('K'K
 // JJ$$%8%F%FGM =!Q& -m < J J L.;+6:jj$$%8%N%NO73 ! r+   c                   U R                   c  [        U R                  5      U l         U R                   nUR                  U5        [	        SSS5      UR
                  l        [        UR
                  l        SUR
                  l	        SUR
                  l
        SUR
                  l        SUR
                  l        [        5       nUR                  U5        UR                  U5        U R!                  5         g)a  Set clipping path in block coordinates (relative to block origin).

The clipping path is located in the xy-plane, the z-axis of all vertices will
be ignored.  The clipping path doesn't have to be closed (first vertex != last vertex).
Two vertices define a rectangle where the sides are parallel to x- and y-axis.

Raises:
   DXFValueError: clipping path has less than two vertrices

Nr           )rB   new_spatial_filterrA   set_boundary_verticesr   rU   originr   	extrusionhas_front_clipping_planefront_clipping_plane_distancehas_back_clipping_planeback_clipping_plane_distancer   set_inverse_insert_matrixset_transform_matrix_discard_inverted_clip)r'   r    spatial_filterrn   s       r)   set_block_clipping_pathXClip.set_block_clipping_path   s     '#5dll#CD --,,X6$(AqM!'-$673;>8562:=7
 J003++A.##%r+   c                ,   U R                   R                  5       n UR                  5         [        R
                  " U5      n[        U5      S:X  a  [        U5      nU R                  UR                  U5      5        g! [         a    [        S5      ef = f)a  Set clipping path in WCS coordinates (relative to WCS origin).

The clipping path is located in the xy-plane, the z-axis of all vertices will
be ignored. The clipping path doesn't have to be closed (first vertex != last vertex).
Two vertices define a rectangle where the sides are parallel to x- and y-axis.

Raises:
   DXFValueError: clipping path has less than two vertrices
   ZeroDivisionError: Block reference transformation matrix is not invertible

z8Block reference transformation matrix is not invertible.rJ   N)
rA   rs   inverseZeroDivisionErrorr   listrk   rl   r   ri   )r'   r    rn   	_verticess       r)   set_wcs_clipping_pathXClip.set_wcs_clipping_path   s     LL!!#	IIK
 IIh'	y>Q"9-I$$Q%9%9)%DE ! 	#J 	s   A= =BNF)ignore_acad_compatibilityc                  USL a  gU R                  5       n[        UR                  5      S:  a  [        R                  " S5      eUR
                  (       a  [        R                  " S5      eU R                  R                  c   eU R                  R                  R                  S5        SnUc  U R                  5       nSn[        U5      nUR                  UR                  5        UR                  (       d  [        R                  " S	5      eU(       a'  UR                  [        UR                  5      U-  5        UR                  n[!        XV5      nU R#                  U5        U R%                  Xg5        g)
a  Invert clipping path. (experimental feature)

The outer boundary is defined by the bounding box of the given `extents`
vertices or auto-detected if `extents` is ``None``.

The `extents` are BLOCK coordinates.
Requires an existing clipping path and that clipping path cannot be inverted.

.. warning::

    You have to set the flag `ignore_acad_compatibility` to ``True`` to use
    this feature.  AutoCAD will not load DXF files with inverted clipping paths
    created by ezdxf!!!!

FNrJ   zno clipping path setz!clipping path is already invertedzN
AutoCAD will not load DXF files with inverted clipping paths created by ezdxfrz   g?zextents not detectable)rp   rk   r    r   DXFValueErrorr$   rA   rK    add_acad_incompatibility_message_detect_block_extentsr   extendhas_datagrowmaxsize#_get_inverted_clip_compare_verticesr   _set_inverted_clipping_path)r'   extentsr   current_clipping_pathgrow_factorbboxr!   r"   s           r)   invert_clipping_pathXClip.invert_clipping_path   s8   $ %- $ < < >$--.2%%&<== 11%%&IJJ||+++99]	
 ?002G KW%)223}}%%&>??IIc$))n{23 .66 CD X$$%:;((Nr+   c                l   SSK Jn  U R                  nUR                  nUc   S5       e[	        5       nUR
                  R                  UR                  R                  5      nUc  U$ UR                  USS9nUR                  (       d  U$ [        R                  " UR                  UR                  /5      $ )Nr   )r   zvalid DXF document requiredT)fast)ezdxfr   rA   rK   r8   blocksrM   rU   namer   r   r   extminextmax)r'   r   rC   rK   no_verticesblock_bboxs          r)   r   XClip._detect_block_extents)  s    jj= ==&+g

vzz/=U.~~zz5<<677r+   c                   U R                   n[        U[        5      (       d   e[        U5      nUc  [	        U5      n[        S U 5       5      n[        S U 5       5      nUR                  [        U5        UR                  [        U5        g )Nc              3  L   #    U  H  n[        S [        U5      5      v   M     g7f
   Nr   r   .0vs     r)   	<genexpr>4XClip._set_inverted_clipping_path.<locals>.<genexpr>B  s     DmDG,,m   "$c              3  L   #    U  H  n[        S [        U5      5      v   M     g7fr   r   r   s     r)   r   r   C  s      J9IAF2tAw//9Ir   )	rB   r>   r	   rY   new_roundtrip_xrecordr   set_sectionr   r   )r'   clip_verticescompare_verticesr   r[   	clip_tagscompare_tagss          r)   r   !XClip._set_inverted_clipping_path9  s~     --.-8888$^4<(8DDmDD	J9IJJ4i@<lKr+   c                0   [        U R                  [        5      (       d  gU R                  R	                  5       nUR                  [        5        U R                  R                  R                  nUc   eUR                  U R                  5        SU l        g)zDelete the clipping path. The clipping path doesn't have to exist.

This method does not discard the extension dictionary of the base entity,
even when its empty.
N)
r>   rB   r	   rA   get_extension_dictdiscardr   rK   entitydbdelete_entity)r'   xdictr   s      r)   discard_clipping_pathXClip.discard_clipping_pathG  su     $..>>//1k"<<##,,###t334#r+   c                x    [        U R                  [        5      (       a  U R                  R                  5         g g N)r>   rB   r	   discard_extension_dictr-   s    r)   r   XClip._discard_inverted_clipW  s,    d**M::  779 ;r+   c                8    U R                   R                  5         g)z?Discard the extension dictionary of the base entity when empty.N)rA   discard_empty_extension_dictr-   s    r)   cleanupXClip.cleanup[  s    113r+   )rA   rB   )rC   r   r2   None)r2   SpatialFilter | None)r2   int)r2   r#   )r2   r   )r2   r   )r    zIterable[UVec]r2   r   r   )r   zIterable[UVec] | Noner2   r   r1   )r   Iterable[Vec2]r   r   r2   r   )r3   r4   r5   r6   r7   rD   r   rO   propertyrR   rV   r$   r`   rd   rp   rw   r   r   r   r   r   r   r   r   r:   r0   r+   r)   r   r   C   s    ,:$ 0 0   = ==
=
0!6&<F2 044ORW4O,4O	4Ol8 L+L?ML	L$ :4r+   r   c                4    [        U 5      R                  5       $ )z[Returns the path vertices for the smallest rectangular boundary around the given
vertices.
)r   rt   )r    s    r)   rl   rl   `  s     "0022r+   c                f    SSK Jn  U R                  b  U R                  c   eU" [	        U5      U S9$ )Nr   )make_inverted_clipping_polygon)r(   r.   )ezdxf.math.clippingr   r   r   r   )r   holer   s      r)   r   r   g  s3    
 CKK#$++*ABB)T
QUVVr+   c                     U R                  5       nUR                  [        5      n[	        U[
        5      (       d  gUR                  [        5      n[	        U[        5      (       a  U$ g! [         a     gf = f)zxReturns the underlaying SPATIAL_FILTER entity if the given `entity` has a
clipping path and returns ``None`` otherwise.
N)r   AttributeErrorrM   r   r>   r   r   r	   )entityr   acad_filteracad_spatial_filters       r)   r   r   r  so    ))+ ))K(Kk:..%//'2%}55""  s   A* *
A76A7c                   U R                   nUc  [        R                  " S5      e U R                  5       nUR                  R                  [        5      nUR                  [        5      n[        U[        5      (       dH  UR                  R                  SSUR                  R                   05      nUR#                  [        U5        [        U[        5      (       d   eU$ ! [         a    U R                  5       n Nf = f)zgCreates the extension dict, the sub-dictionary ACAD_FILTER and the SPATIAL_FILTER
entity if not exist.
z/Cannot add new clipping path to virtual entity.SPATIAL_FILTERowner)rK   r   r?   r   r   new_extension_dict
dictionaryget_required_dictr   rM   r   r>   r	   objectsadd_dxf_object_with_reactorrU   handleadd)r   rK   r   acad_filter_dictr   s        r)   r{   r{     s     **C
{  !RSS,))+ ''99+F%))'2Nnm44@@w(8(<(<(C(CD
 	Wn5nm4444  ,))+,s   C! !C>=C>c                :    U R                  5       nUR                  [        5      nUc1  UR                  [        5      nUR                  UR                  /5        [        U[        5      (       d   e[        U5      $ ! [         a    U R                  5       n Nf = fr   )r   r   r   rM   r   add_xrecordset_reactorsr   r>   r   r   )r   r   r[   s      r)   r   r     s    4113 99()D|  !455<<.)dG$$$$D!!  41134s   A= =BBc                    U c  g  U R                  5       nUR                  [        5      n[	        U[
        5      (       a  [        U5      $ g ! [         a     g f = fr   )r   r   rM   r   r>   r   r   )r   r   xrecords      r)   rY   rY     s`     113 ii+,G'7##((  s   A 
AAc                    U R                  U5      nUR                  S U 5       5      n[        R                  " U5      $ )Nc              3  L   #    U  H  n[        UR                  5      v   M     g 7fr   )r   value)r   ts     r)   r   )get_roundtrip_vertices.<locals>.<genexpr>  s     #@4aDMM4r   )get_sectionri   r   r8   )r[   section_namern   tagsr    s        r)   rm   rm     s9     L)D###@4#@@H::hr+   c                    [        U 5      nUR                  (       a%  UR                  nUR                  UR                  -  $ g)Nrz   )r   r   r   xy)verticer   r   s      r)   r&   r&     s1    !D}}yyvvr+   )r    r   r2   r   )r   r   r   r   r2   r   )r   r
   r2   r   )r   r
   r2   r	   )r   r	   r2   r   )r   r   r2   zRoundtripXRecord | None)r[   r   r   r@   rn   r   r2   r   )r   r   r2   float),
__future__r   typingr   r   dataclassesezdxf.lldxfr   ezdxf.lldxf.tagsr   ezdxf.lldxf.typesr   ezdxf.entitiesr	   r
   r   r   r   
ezdxf.mathr   r   r   r   r   r   "ezdxf.entities.acad_xrec_roundtripr   __all__r   r   r   r   r   	dataclassr   r   rl   r   r   r{   r   rY   rm   r&   r0   r+   r)   <module>r     s    # %   ! $ P P H H ?
9+ ; &K #
 '9 '9 '9TZ4 Z4z3W
W-WW",
"( 
 *- 2:  r+   