o
    jk*                     @   s@   d Z ddlZddlZddlmZ ddlmZ G dd deZdS )a  Object with a bounding box, e.g. Block, Line, Span.

Based on ``PyMuPDF``, the coordinates (e.g. bbox of ``page.get_text('rawdict')``) are generally
provided relative to the un-rotated page; while this ``pdf2docx`` library works under real page
coordinate system, i.e. with rotation considered. So, any instances created by this Class are
always applied a rotation matrix automatically.

Therefore, the bbox parameter used to create ``Element`` instance MUST be relative to un-rotated
CS. If final coordinates are provided, should update it after creating an empty object::

    Element().update_bbox(final_bbox)

.. note::
    An exception is ``page.get_drawings()``, the coordinates are converted to real page CS already.
    N   )IText)	constantsc                	   @   s
  e Zd ZdZedZedd Zedd Z	d6de
fd	d
Zdd Zdd Zedd Zejdd Zdd ZdefddZdd Zdd Zd7dd defddZd8defd!d"Zd9d$ed%efd&d'Zd9d$ed%efd(d)Zd*d+ Zd,d- Zd:d0ed1ed2ed3efd4d5ZdS );Elementz.Boundary box with attribute in fitz.Rect type.        c                 C   s"   |rt |tjr|| _dS dS dS )zlSet global rotation matrix.

        Args:
            Rotation_matrix (fitz.Matrix): target matrix
        N)
isinstancefitzMatrixROTATION_MATRIX)clsZrotation_matrix r   X/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/pdf2docx/common/Element.pyset_rotation_matrix   s   
zElement.set_rotation_matrixc                 C   s&   | j \}}}}}}t||||ddS )zHPure rotation matrix used for calculating text direction after rotation.r   )r
   r   r	   )r   abcdefr   r   r   pure_rotation_matrix*   s   zElement.pure_rotation_matrixNrawc                 C   sB   t  | _|| _d|pi v rt |d tj }| | dS dS )zJ Initialize Element and convert to the real (rotation considered) page CS.bboxN)r   Rectr   _parentr   r
   update_bbox)selfr   parentrectr   r   r   __init__1   s   
zElement.__init__c                 C   s
   t | jS )z!Real object when bbox is defined.)boolr   r   r   r   r   __bool__=   s   
	zElement.__bool__c                 C   s   | j j dt| j dS )N())	__class____name__tupler   r    r   r   r   __repr__I   s    zElement.__repr__c                 C   s   | j S Nr   r    r   r   r   r   O   s   zElement.parentc                 C   s
   || _ d S r(   r)   )r   r   r   r   r   r   R   s   
c                 C   s"   | j d}| _t| }|| _ |S )zmake a deep copy.N)r   r   copydeepcopy)r   r   objr   r   r   r*   Y   s   
zElement.copydtc                 C   s   | j | | ||f S )a  Get expanded bbox with margin in both x- and y- direction.

        Args:
            dt (float): Expanding margin.

        Returns:
            fitz.Rect: Expanded bbox.

        .. note::
            This method creates a new bbox, rather than changing the bbox of itself.
        )r   )r   r-   r   r   r   get_expand_bboxc   s   zElement.get_expand_bboxc                 C   s   t dd |D | _| S )zUpdate current bbox to specified ``rect``.

        Args:
            rect (fitz.Rect or list): bbox-like ``(x0, y0, x1, y1)``,
                in real page CS (with rotation considered).
        c                 S   s   g | ]}t |d qS )r   )round.0xr   r   r   
<listcomp>y   s    z'Element.update_bbox.<locals>.<listcomp>)r   r   r   )r   r   r   r   r   r   r   s   zElement.update_bboxc                 C   s   |  | j|jB S )zUpdate current bbox to the union with specified Element.

        Args:
            e (Element): The target to get union

        Returns:
            Element: self
        )r   r   )r   r   r   r   r   
union_bbox}   s   	zElement.union_bbox      ?r   	thresholdc                 C   sx   |j  }|s	dS | j |j @ }t| | d}||k rdS | j j| j jkr1| j jtj |j jkS | j jtj |j jkS )a5  Whether given element is contained in this instance, with margin considered.

        Args:
            e (Element): Target element
            threshold (float, optional): Intersection rate.
                Defaults to 1.0. The larger, the stricter.

        Returns:
            bool: [description]
        F   )r   get_arear/   widthheightr   Z
MINOR_DIST)r   r   r6   Sintersectionfactorr   r   r   contains   s   
zElement.containsffffff?c           
      C   sx   | j }t|dr|j nt|}||@ }|jrdS | | | }}}|r0|t|| nd}	|	|kr:||B S dS )aC  If the intersection with ``e`` exceeds the threshold, return the union of
        these two elements; else return None.

        Args:
            e (Element): Target element.
            threshold (float, optional): Intersection rate. Defaults to 0.95.

        Returns:
            fitz.Rect: Union bbox or None.
        r   Ngư>)r   hasattrr   r   Zis_emptyr8   min)
r   r   r6   Zbbox_1Zbbox_2r   Za1Za2r   r=   r   r   r   get_main_bbox   s   
zElement.get_main_bboxTr=   text_directionc           	      C      |rt | sdS |r| jrdnd}| j|d  | j|  }|j|d  |j|  }t| j|d  |j|d  t| j| |j|  }d}|| | | |t|| kS )a  Check whether two Element instances have enough intersection in vertical direction,
        i.e. perpendicular to reading direction.

        Args:
            e (Element): Object to check with
            factor (float, optional): Threshold of overlap ratio, the larger it is, the higher
                probability the two bbox-es are aligned.
            text_direction (bool, optional): Consider text direction or not. True by default.

        Returns:
            bool: [description]

        Examples::

            +--------------+
            |              |
            +--------------+
                    L1
                    +-------------------+
                    |                   |
                    +-------------------+
                            L2

        An enough intersection is defined based on the minimum width of two boxes::

            L1+L2-L>factor*min(L1,L2)
        Fr   r   r7   MbP?r   Zis_vertical_textr   maxrA   	r   r   r=   rC   idxZL1ZL2Lepsr   r   r   vertically_align_with   s   4zElement.vertically_align_withc           	      C   rD   )a  Check whether two Element instances have enough intersection in horizontal direction,
        i.e. along the reading direction.

        Args:
            e (Element): Element to check with
            factor (float, optional): threshold of overlap ratio, the larger it is, the higher
                probability the two bbox-es are aligned.
            text_direction (bool, optional): consider text direction or not. True by default.

        Examples::

            +--------------+
            |              | L1  +--------------------+
            +--------------+     |                    | L2
                                 +--------------------+

        An enough intersection is defined based on the minimum width of two boxes::

            L1+L2-L>factor*min(L1,L2)
        Fr   r   r7   rE   rF   rH   r   r   r   horizontally_align_with   s   4zElement.horizontally_align_withc                 C   s   |r| j |j kr
dS | j rdnd}| j| | j|d   d }|j| |j|d   d }||j|d  ko>|| j|d  k}|S )a  Check whether in same row/line with specified Element instance.
        With text direction considered.

           Taking horizontal text as an example:

           * yes: the bottom edge of each box is lower than the centerline of the other one;
           * otherwise, not in same row.

        Args:
            e (Element): Target object.

        .. note::
            The difference to method ``horizontally_align_with``: they may not in same line, though
            aligned horizontally.
        Fr   r   r7   g       @)Zis_horizontal_textr   )r   r   rI   c1c2resr   r   r   in_same_row  s   $zElement.in_same_rowc                 C   s   dt dd | jD iS )zStore properties in raw dict.r   c                 s   s    | ]}|V  qd S r(   r   r0   r   r   r   	<genexpr>-  s    z Element.store.<locals>.<genexpr>)r&   r   r    r   r   r   store+  s   zElement.storer   r   r         ?stroker9   filldashesc              	   C   s   |j | j||||ddd dS )z(Plot bbox in PDF page for debug purpose.FrU   )colorrW   r9   rX   overlayZfill_opacityN)Z	draw_rectr   )r   pagerV   r9   rW   rX   r   r   r   plot0  s   
zElement.plot)NN)r5   )r?   )r   T)rT   rU   NN) r%   
__module____qualname____doc__r   r	   r
   classmethodr   r   dictr   r!   r'   propertyr   setterr*   floatr.   r   r4   r>   rB   r   rL   rM   rQ   rS   r&   strr\   r   r   r   r   r      s2    






)" r   )r_   r*   r   Zsharer    r   r   r   r   r   r   <module>   s    