
    OgE                    Z   d dl mZ d dlmZmZ d dlZd dlm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mZmZmZmZmZ d d	lmZ g d
ZdZdZdZdZdZ ejB                   G d d             Z" G d d      Z#ddZ$	 	 	 	 	 	 ddZ%ddZ&ddZ'd dZ(	 	 	 	 d!dZ)	 	 	 	 	 	 	 	 d"dZ*d#dZ+y)$    )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                  x    e Zd ZU dZ e       Zded<    e       Zded<    e       Zded<   dZ	ded<   dd	Z
dd
Zy)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                    | j                   s| j                  S | j                  }t        | j                        t        |      k  r| j                  }|S )z7Returns the inner clipping polygon as sequence of Vec2.)r#   r   	bbox_arear    )selfinner_polygons     P/var/www/html/public_html/myphp/venv/lib/python3.12/site-packages/ezdxf/xclip.pyr'   zClippingPath.inner_polygon/   sI     $$== T''(9]+CC ..M    c                n    | j                   st        | j                        S t        | j                        S )z-Returns the maximum extents as BoundingBox2d.)r#   r   r   r!   r&   s    r(   outer_boundszClippingPath.outer_bounds:   s-    $$ // T7788r)   Nreturnr   )r.   r   )__name__
__module____qualname____doc__tupler   __annotations__r    r!   r#   r'   r,    r)   r(   r   r      sC       %wHn&$)GM>+,1G>3"d"	9r)   r   c                      e Zd ZdZddZddZddZedd       Zedd       Z	edd       Z
ddZdd	Zdd
ZddZddZddZ	 ddd	 	 	 ddZd dZ	 	 	 	 	 	 d!dZddZddZd Zy)"r   a}  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                    t        |t              s!t        j                  dt	        |             || _        t        |      | _        y )NzINSERT entity required, got )
isinstancer   r   DXFTypeErrorstr_insertr   _spatial_filter)r&   inserts     r(   __init__zXClip.__init__Z   s=    &&)$$'CCK=%QRR1&9r)   c                    | j                   S )zReturns the underlaying SPATIAL_FILTER entity if the INSERT entity has a
        clipping path and returns ``None`` otherwise.
        r<   r+   s    r(   r   zXClip.get_spatial_filter`   s     ###r)   c                    d}| j                   j                  0| j                   j                  j                  j                  dd      }|S )N   z$XCLIPFRAME)r;   docheaderget)r&   policys     r(   get_xclip_frame_policyzXClip.get_xclip_frame_policyf   s>    <<'\\%%,,00BFr)   c                    | j                   duS )z1Returns if the INSERT entity has a clipping path.Nr@   r+   s    r(   has_clipping_pathzXClip.has_clipping_pathl   s     ##4//r)   c                    t        | j                  t              r)t        | j                  j                  j
                        S y)z8Returns ``True`` if block reference clipping is enabled.F)r8   r<   r	   r"   dxfis_clipping_enabledr+   s    r(   rL   zXClip.is_clipping_enabledq   s4     d**M:,,00DDEEr)   c                \    t        | j                        }|y|j                  t              S )z.Returns ``True`` if clipping path is inverted.F)get_roundtrip_xrecordr<   has_sectionr   )r&   xrecs     r(   r#   zXClip.is_inverted_clipx   s.     %T%9%9:< ;<<r)   c                p    t        | j                  t              rd| j                  j                  _        yy)z Enable block reference clipping.   Nr8   r<   r	   rK   rL   r+   s    r(   enable_clippingzXClip.enable_clipping   +    d**M:;<D  $$8 ;r)   c                p    t        | j                  t              rd| j                  j                  _        yy)z!Disable block reference clipping.r   NrS   r+   s    r(   disable_clippingzXClip.disable_clipping   rU   r)   c                   g }t        | j                  t              s
t               S | j                  j                  }t        j                  |j                  | j                  j                              }t        |      dk(  rt        |      }t        |d      }t        | j                        }t        |t              r3t        |t        |      |_        t        |t         |      |_        d|_        |S )zNReturns the clipping path in block coordinates (relative to the block origin).rB   Fr#   T)r8   r<   r	   r   inverse_insert_matrixr   r3   transform_verticesboundary_verticeslen
_rect_pathrN   r   get_roundtrip_verticesr   r    r   r!   r#   )r&   r   mclipping_pathrP   s        r(   get_block_clipping_pathz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                   t               }t        | j                  t              st	        ||      S | j                         }| j                  j                         }t        j                   |j                  |j                              }t        |      dk(  rt        |      j                         }t	        ||j                        }|j                  rt        j                   |j                  |j                              }t        |      dk(  rt        |      j                         }||_        t        j                   |j                  |j                               |_        |S )zReturns the clipping path in WCS coordinates (relative to the WCS origin) as
        2D path projected onto the xy-plane.
        rB   rY   )r3   r8   r<   r	   r   rb   r;   matrix44r   r[   r   r]   r   rect_verticesr#   r    r!   )r&   r   block_clipping_pathr`   wcs_clipping_pathr    s         r(   get_wcs_clipping_pathz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                   | j                   t        | j                        | _         | j                   }|j                  |       t	        ddd      |j
                  _        t        |j
                  _        d|j
                  _	        d|j
                  _
        d|j
                  _        d|j
                  _        t               }|j                  |       |j                  |       | j!                          y)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           )r<   new_spatial_filterr;   set_boundary_verticesr   rK   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_filterr`   s       r(   set_block_clipping_pathzXClip.set_block_clipping_path   s     '#5dll#CD --,,X6$(AqM!'-$673;>8562:=7
 J003++A.##%r)   c                &   | j                   j                         }	 |j                          t	        j
                  |      }t        |      dk(  rt        |      }| j                  |j                  |             y# t        $ r t        d      w xY w)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.rB   N)
r;   rd   inverseZeroDivisionErrorr   listr]   r^   rw   r[   )r&   r   r`   	_verticess       r(   set_wcs_clipping_pathz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                  |du ry| j                         }t        |j                        dk  rt        j                  d      |j
                  rt        j                  d      | j                  j                  J | j                  j                  j                  d       d}|| j                         }d}t        |      }|j                  |j                         |j                  st        j                  d	      |r'|j                  t        |j                        |z         |j                  }t!        ||      }| j#                  |       | j%                  ||       y)
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!!!!

        FNrB   zno clipping path setz!clipping path is already invertedzN
AutoCAD will not load DXF files with inverted clipping paths created by ezdxfrj   g?zextents not detectable)rb   r]   r   r   DXFValueErrorr#   r;   rC    add_acad_incompatibility_message_detect_block_extentsr   extendhas_datagrowmaxsize#_get_inverted_clip_compare_verticesrw   _set_inverted_clipping_path)r&   extentsr~   current_clipping_pathgrow_factorbboxr    r!   s           r(   invert_clipping_pathzXClip.invert_clipping_path   s=   $ %- $ < < >$--.2%%&<== 11%%&IJJ||+++99]	
 ?002G KW%)223}}%%&>??IIc$))n{23 .66 CD- X$$%:;((8MNr)   c                b   ddl m} | j                  }|j                  }|J d       t	               }|j
                  j                  |j                  j                        }||S |j                  |d      }|j                  s|S t        j                  |j                  |j                  g      S )Nr   )r   zvalid DXF document requiredT)fast)ezdxfr   r;   rC   r3   blocksrE   rK   namer   r   r   extminextmax)r&   r   r=   rC   no_verticesblock_bboxs          r(   r   zXClip._detect_block_extents)  s    jj= ==&+g

vzz/=U.~~zz5<<677r)   c                   | j                   }t        |t              sJ t        |      }|t	        |      }t        d |D              }t        d |D              }|j                  t        |       |j                  t        |       y )Nc              3  F   K   | ]  }t        d t        |              yw
   Nr   r   .0vs     r(   	<genexpr>z4XClip._set_inverted_clipping_path.<locals>.<genexpr>B  s     DDG,D   !c              3  F   K   | ]  }t        d t        |              ywr   r   r   s     r(   r   z4XClip._set_inverted_clipping_path.<locals>.<genexpr>C  s     JAF2tAw/Jr   )	r<   r8   r	   rN   new_roundtrip_xrecordr   set_sectionr   r   )r&   clip_verticescompare_verticesrv   rP   	clip_tagscompare_tagss          r(   r   z!XClip._set_inverted_clipping_path9  s{     --.-888$^4<(8DDmDD	J9IJJ4i@<lKr)   c                $   t        | j                  t              sy| j                  j	                         }|j                  t               | j                  j                  j                  }|J |j                  | j                         d| _        y)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)
r8   r<   r	   r;   get_extension_dictdiscardr   rC   entitydbdelete_entity)r&   xdictr   s      r(   discard_clipping_pathzXClip.discard_clipping_pathG  sr     $..>//1k"<<##,,###t334#r)   c                n    t        | j                  t              r| j                  j                          y y N)r8   r<   r	   discard_extension_dictr+   s    r(   ru   zXClip._discard_inverted_clipW  s)    d**M:  779 ;r)   c                8    | j                   j                          y)z?Discard the extension dictionary of the base entity when empty.N)r;   discard_empty_extension_dictr+   s    r(   cleanupzXClip.cleanup[  s    113r)   )r=   r   r.   None)r.   SpatialFilter | None)r.   int)r.   r"   )r.   r   )r.   r   )r   zIterable[UVec]r.   r   r   )r   zIterable[UVec] | Noner.   r   r-   )r   Iterable[Vec2]r   r   r.   r   )r/   r0   r1   r2   r>   r   rG   propertyrI   rL   r#   rT   rW   rb   rh   rw   r}   r   r   r   r   ru   r   r5   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    t        |       j                         S )zcReturns the path vertices for the smallest rectangular boundary around the given
    vertices.
    )r   re   )r   s    r(   r^   r^   `  s     "0022r)   c                h    ddl m} | j                  | j                  J  |t	        |      |       S )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                    	 | j                         }|j                  t              }t	        |t
              sy|j                  t              }t	        |t              r|S y# t        $ r Y yw xY w)zReturns the underlaying SPATIAL_FILTER entity if the given `entity` has a
    clipping path and returns ``None`` otherwise.
    N)r   AttributeErrorrE   r   r8   r   r   r	   )entityr   acad_filteracad_spatial_filters       r(   r   r   r  si    ))+ ))K(Kk:.%//'2%}5""  s   A   	A,+A,c                   | j                   }|t        j                  d      	 | j                         }|j                  j                  t              }|j                  t              }t        |t              sH|j                  j                  dd|j                  j                   i      }|j#                  t        |       t        |t              sJ |S # t        $ r | j                         }Y w xY w)zoCreates 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)rC   r   r9   r   r   new_extension_dict
dictionaryget_required_dictr   rE   r   r8   r	   objectsadd_dxf_object_with_reactorrK   handleadd)r   rC   r   acad_filter_dictrv   s        r(   rk   rk     s     **C
{  !RSS,))+ ''99+F%))'2Nnm4@@w(8(<(<(C(CD
 	Wn5nm444  ,))+,s   C C10C1c                ,   	 | j                         }|j                  t              }|1|j                  t              }|j                  |j                  g       t        |t              sJ t        |      S # t        $ r | j                         }Y w xY wr   )r   r   r   rE   r   add_xrecordset_reactorsr   r8   r   r   )rv   r   rP   s      r(   r   r     s    4113 99()D|  !455<<.)dG$$$D!!  41134s   A7 7BBc                    | y 	 | j                         }|j                  t              }t	        |t
              rt        |      S y # t        $ r Y y w xY wr   )r   r   rE   r   r8   r   r   )rv   r   xrecords      r(   rN   rN     s]     113 ii+,G'7#((  s   A 	AAc                ~    | j                  |      }|j                  d |D              }t        j                  |      S )Nc              3  F   K   | ]  }t        |j                          y wr   )r   value)r   ts     r(   r   z)get_roundtrip_vertices.<locals>.<genexpr>  s     #@aDM#@r   )get_sectionr[   r   r3   )rP   section_namer`   tagsr   s        r(   r_   r_     s9     L)D###@4#@@H::hr)   c                |    t        |       }|j                  r%|j                  }|j                  |j                  z  S y)Nrj   )r   r   r   xy)verticer   r   s      r(   r%   r%     s1    !D}}yyvvr)   )r   r   r.   r   )r   r   r   r   r.   r   )r   r
   r.   r   )r   r
   r.   r	   )rv   r	   r.   r   )rv   r   r.   zRoundtripXRecord | None)rP   r   r   r:   r`   r   r.   r   )r   r   r.   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   r^   r   r   rk   r   rN   r_   r%   r5   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)   