o
    hiJ                     @   s   d Z ddlmZ ddlZddlZddlZddlmZ ej	edddd Z
G d	d
 d
eZdd Zdd Zdd Zdd Z	d-ddZG dd dZ	d.ddZd/ddZdd  Zd!d" Zd0d$d%Zd&d' Zd(d) Zd1d+d,ZdS )2uP   
A module providing some utility functions regarding Bézier path manipulation.
    )	lru_cacheN)_api   )maxsizec                 C   sF   || krdS t || | }td|d }t| d | | tS )Nr      )minnparangeprodastypeint)nki r   e/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/matplotlib/bezier.py_comb   s
   r   c                   @   s   e Zd ZdS )NonIntersectingPathExceptionN)__name__
__module____qualname__r   r   r   r   r      s    r   c                    s   ||  ||  }|| ||  }	|| }
}|| }}|
| ||   t  dk r.td|| }}| |
}} fdd||||fD \}}}}|| ||	  }|| ||	  }||fS )z
    Return the intersection between the line through (*cx1*, *cy1*) at angle
    *t1* and the line through (*cx2*, *cy2*) at angle *t2*.
    g-q=zcGiven lines do not intersect. Please verify that the angles are not equal or differ by 180 degrees.c                 3   s    | ]}|  V  qd S )Nr   ).0r   ad_bcr   r   	<genexpr>9   s    z#get_intersection.<locals>.<genexpr>)abs
ValueError)cx1cy1cos_t1sin_t1cx2cy2cos_t2sin_t2	line1_rhs	line2_rhsabcda_b_c_d_xyr   r   r   get_intersection    s   
"r1   c                 C   sl   |dkr
| || |fS || }}| |}}|| |  || | }	}
|| |  || | }}|	|
||fS )z
    For a line passing through (*cx*, *cy*) and having an angle *t*, return
    locations of the two points located along its perpendicular line at the
    distance of *length*.
            r   )cxcycos_tsin_tlengthr   r    r#   r$   x1y1x2y2r   r   r   get_normal_pointsA   s   r<   c                 C   s(   | d d d|  | dd  |  }|S )Nr   r   )betat	next_betar   r   r   _de_casteljau1Z   s   $rA   c                 C   s^   t | } | g}	 t| |} ||  t| dkrnq	dd |D }dd t|D }||fS )u   
    Split a Bézier segment defined by its control points *beta* into two
    separate segments divided at *t* and return their control points.
    Tr   c                 S      g | ]}|d  qS )r   r   r   r>   r   r   r   
<listcomp>k       z&split_de_casteljau.<locals>.<listcomp>c                 S   rB   )r=   r   rC   r   r   r   rD   l   rE   )r   asarrayrA   appendlenreversed)r>   r?   	beta_list	left_beta
right_betar   r   r   split_de_casteljau_   s   


rM   r2         ?{Gz?c                 C   s   | |}| |}||}||}||kr||krt d	 t|d |d  |d |d  |k r5||fS d||  }	| |	}
||
}||A rT|	}||
krQ||fS |
}n|	}||
kr^||fS |
}|}q)u  
    Find the intersection of the Bézier curve with a closed path.

    The intersection point *t* is approximated by two parameters *t0*, *t1*
    such that *t0* <= *t* <= *t1*.

    Search starts from *t0* and *t1* and uses a simple bisecting algorithm
    therefore one of the end points must be inside the path while the other
    doesn't. The search stops when the distance of the points parametrized by
    *t0* and *t1* gets smaller than the given *tolerance*.

    Parameters
    ----------
    bezier_point_at_t : callable
        A function returning x, y coordinates of the Bézier at parameter *t*.
        It must have the signature::

            bezier_point_at_t(t: float) -> tuple[float, float]

    inside_closedpath : callable
        A function returning True if a given point (x, y) is inside the
        closed path. It must have the signature::

            inside_closedpath(point: tuple[float, float]) -> bool

    t0, t1 : float
        Start parameters for the search.

    tolerance : float
        Maximal allowed distance between the final points.

    Returns
    -------
    t0, t1 : float
        The Bézier path parameters.
    z3Both points are on the same side of the closed pathTr   r         ?)r   r   hypot)bezier_point_at_tinside_closedpatht0t1	tolerancestartendstart_inside
end_insidemiddle_tmiddlemiddle_insider   r   r   *find_bezier_t_intersecting_with_closedpathq   s2   &(r^   c                   @   s`   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
edd Zdd ZdS )BezierSegmentu   
    A d-dimensional Bézier segment.

    Parameters
    ----------
    control_points : (N, d) array
        Location of the *N* control points.
    c                    sV   t | _ jj\ _ _t  j _ fddt jD } jj	| j	 _
d S )Nc                    s:   g | ]}t  jd  t |t  jd  |   qS )r   )math	factorial_N)r   r   selfr   r   rD      s
    z*BezierSegment.__init__.<locals>.<listcomp>)r   rF   _cpointsshaperb   _dr	   _ordersrangeT_px)rd   control_pointscoeffr   rc   r   __init__   s   
zBezierSegment.__init__c                 C   s>   t |}t jd| | jddd t j|| j | j S )u)  
        Evaluate the Bézier curve at point(s) *t* in [0, 1].

        Parameters
        ----------
        t : (k,) array-like
            Points at which to evaluate the curve.

        Returns
        -------
        (k, d) array
            Value of the curve for each point in *t*.
        r   Nr=   )r   rF   powerouterrh   rk   rd   r?   r   r   r   __call__   s   
zBezierSegment.__call__c                 C   s   t | |S )zX
        Evaluate the curve at a single point, returning a tuple of *d* floats.
        )tuplerq   r   r   r   
point_at_t   s   zBezierSegment.point_at_tc                 C      | j S )z The control points of the curve.)re   rc   r   r   r   rl         zBezierSegment.control_pointsc                 C   ru   )zThe dimension of the curve.)rg   rc   r   r   r   	dimension   rv   zBezierSegment.dimensionc                 C   s
   | j d S )z@Degree of the polynomial. One less the number of control points.r   )rb   rc   r   r   r   degree   s   
zBezierSegment.degreec                 C   s|   | j }|dkrtdt | j}t|d dddf }t|d dddf }d||  t|| }t||| | S )u  
        The polynomial coefficients of the Bézier curve.

        .. warning:: Follows opposite convention from `numpy.polyval`.

        Returns
        -------
        (n+1, d) array
            Coefficients after expanding in polynomial basis, where :math:`n`
            is the degree of the Bézier curve and :math:`d` its dimension.
            These are the numbers (:math:`C_j`) such that the curve can be
            written :math:`\sum_{j=0}^n C_j t^j`.

        Notes
        -----
        The coefficients are calculated as

        .. math::

            {n \choose j} \sum_{i=0}^j (-1)^{i+j} {j \choose i} P_i

        where :math:`P_i` are the control points of the curve.
        
   zFPolynomial coefficients formula unstable for high order Bezier curves!r   Nr=   )rx   warningswarnRuntimeWarningrl   r   r	   r   )rd   r   Pjr   	prefactorr   r   r   polynomial_coefficients   s   z%BezierSegment.polynomial_coefficientsc           
      C   s   | j }|dkrtg tg fS | j}td|d dddf |dd  }g }g }t|jD ]\}}t|ddd }|| |t	|| q1t
|}t
|}t||dk@ |dk@ }	||	 t||	 fS )a  
        Return the dimension and location of the curve's interior extrema.

        The extrema are the points along the curve where one of its partial
        derivatives is zero.

        Returns
        -------
        dims : array of int
            Index :math:`i` of the partial derivative which is zero at each
            interior extrema.
        dzeros : array of float
            Of same size as dims. The :math:`t` such that :math:`d/dx_i B(t) =
            0`
        r   Nr=   r   )rx   r   arrayr   r	   	enumeraterj   rootsrG   	full_likeconcatenateisrealreal)
rd   r   CjdCjdimsr   r   pirin_ranger   r   r   axis_aligned_extrema  s   (


z"BezierSegment.axis_aligned_extremaN)r   r   r   __doc__rn   rr   rt   propertyrl   rw   rx   r   r   r   r   r   r   r_      s    		



#r_   c           	      C   s>   t | }|j}t|||d\}}t| || d \}}||fS )ur  
    Split a Bézier curve into two at the intersection with a closed path.

    Parameters
    ----------
    bezier : (N, 2) array-like
        Control points of the Bézier segment. See `.BezierSegment`.
    inside_closedpath : callable
        A function returning True if a given point (x, y) is inside the
        closed path. See also `.find_bezier_t_intersecting_with_closedpath`.
    tolerance : float
        The tolerance for the intersection. See also
        `.find_bezier_t_intersecting_with_closedpath`.

    Returns
    -------
    left, right
        Lists of control points for the two Bézier segments.
    )rV   g       @)r_   rt   r^   rM   )	bezierrS   rV   bzrR   rT   rU   _left_rightr   r   r   )split_bezier_intersecting_with_closedpath<  s   
r   Fc                 C   s  ddl m} |  }t|\}}||dd }|}	d}
d}|D ]'\}}|}
|t|d 7 }||dd |krEt|	dd |g} n|}	q td|d}t	|||\}}t|dkrj|j
g}|j|j
g}n2t|d	kr|j|jg}|j|j|jg}nt|d
kr|j|j|jg}|j|j|j|jg}ntd|dd }|dd }| jdu r|t| jd| |g}|t|| j|d g}n2|t| jd|
 |gt| jd|
 |g}|t|| j|d gt|| j|d g}|r|s||}}||fS )z`
    Divide a path into two segments at the point where ``inside(x, y)`` becomes
    False.
    r   )PathNr      z*The path does not intersect with the patch)r=   r         zThis should never be reached)pathr   iter_segmentsnextrH   r   r   r   reshaper   LINETOMOVETOCURVE3CURVE4AssertionErrorcodesvertices)r   insiderV   reorder_inoutr   	path_iter
ctl_pointscommandbegin_insidectl_points_oldioldr   bezier_pathbpleftright
codes_leftcodes_right
verts_leftverts_rightpath_inpath_outr   r   r   split_path_inout_  sV   


r   c                    s   |d  fdd}|S )z
    Return a function that checks whether a point is in a circle with center
    (*cx*, *cy*) and radius *r*.

    The returned function has the signature::

        f(xy: tuple[float, float]) -> bool
    r   c                    s$   | \}}|  d | d  k S )Nr   r   )xyr/   r0   r3   r4   r2r   r   _f  s   zinside_circle.<locals>._fr   )r3   r4   r   r   r   r   r   inside_circle  s   	r   c                 C   sB   ||  || }}|| ||  d }|dkrdS || || fS )NrP   r   )r2   r2   r   )x0y0r8   r9   dxdyr*   r   r   r   get_cos_sin  s
   r   h㈵>c                 C   sJ   t | |}t ||}t|| }||k rdS t|t j |k r#dS dS )a  
    Check if two lines are parallel.

    Parameters
    ----------
    dx1, dy1, dx2, dy2 : float
        The gradients *dy*/*dx* of the two lines.
    tolerance : float
        The angular tolerance in radians up to which the lines are considered
        parallel.

    Returns
    -------
    is_parallel
        - 1 if two lines are parallel in same direction.
        - -1 if two lines are parallel in opposite direction.
        - False otherwise.
    r   r=   F)r   arctan2r   r   )dx1dy1dx2dy2rV   theta1theta2dthetar   r   r   check_if_parallel  s   r   c              	   C   sz  | d \}}| d \}}| d \}}t || || || || }|dkr9td t||||\}	}
|	|
}}nt||||\}	}
t||||\}}t|||	|
|\}}}}t|||||\}}}}zt|||	|
||||\}}t|||	|
||||\}}W n# ty   d||  d||  }}d||  d||  }}Y nw ||f||f||fg}||f||f||fg}||fS )u   
    Given the quadratic Bézier control points *bezier2*, returns
    control points of quadratic Bézier lines roughly parallel to given
    one separated by *width*.
    r   r   r   r=   z8Lines do not intersect. A straight line is used instead.rP   )r   r   warn_externalr   r<   r1   r   )bezier2widthc1xc1ycmxcmyc2xc2yparallel_testr   r    r#   r$   c1x_leftc1y_left	c1x_right	c1y_rightc2x_leftc2y_left	c2x_right	c2y_rightcmx_leftcmy_left	cmx_right	cmy_right	path_left
path_rightr   r   r   get_parallels  sT   


r   c                 C   s>   dd| | |   }dd| ||   }| |f||f||fgS )u   
    Find control points of the Bézier curve passing through (*c1x*, *c1y*),
    (*mmx*, *mmy*), and (*c2x*, *c2y*), at parametric values 0, 0.5, and 1.
    rP   r   r   )r   r   mmxmmyr   r   r   r   r   r   r   find_control_points   s   r   rP   c           %      C   s(  | d \}}| d \}}| d \}	}
t ||||\}}t |||	|
\}}t|||||| \}}}}t|	|
|||| \}}}}|| d || d }}||	 d ||
 d }}|| d || d }}t ||||\}}t|||||| \}} }!}"t|||| ||}#t|||!|"||}$|#|$fS )u   
    Being similar to `get_parallels`, returns control points of two quadratic
    Bézier lines having a width roughly parallel to given one separated by
    *width*.
    r   r   r   rP   )r   r<   r   )%r   r   w1wmw2r   r   r   r   c3xc3yr   r    r#   r$   r   r   r   r   c3x_leftc3y_left	c3x_right	c3y_rightc12xc12yc23xc23yc123xc123ycos_t123sin_t123
c123x_left
c123y_leftc123x_rightc123y_rightr   r   r   r   r   make_wedged_bezier2*  s0   


r   )r2   rN   rO   )rO   )rO   F)r   )rN   rP   r2   )r   	functoolsr   r`   rz   numpyr   
matplotlibr   	vectorizer   r   r   r1   r<   rA   rM   r^   r_   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s6    !
L 

#=
	J
