
     hW8                         d Z ddlmZmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlmZmZmZmZ ddlmZ d Zd	 Zd
 ZddZd Zd Zd Zd Zd Zd Zd Zd Z G d de       Z! G d de"      Z#ddZ$d Z%y)zThis submodule contains tools that deal with generic, degree n, Bezier
curves.
Note:  Bezier curves here are always represented by the tuple of their control
points given by their standard representation.    )divisionabsolute_importprint_function)	factorialceillogsqrt)poly1d   )realimag	polyrootspolyroots01)FLOAT_EPSILONc                 N    t        |       t        |      z  t        | |z
        z  S Nfac)nks     o/home/developers/rajanand/mypropertyqr-fmb-refixing-v2/venv/lib/python3.12/site-packages/svgpathtools/bezier.py
n_choose_kr      s!    q63q6>3qs8##    c                     d|z
  }t        | dz         D cg c]  }t        | |      || |z
  z  z  ||z  z   c}S c c}w )z[returns a list of the Bernstein basis polynomials b_{i, n} evaluated at
    t, for i =0...nr   )ranger   )r   tt1r   s       r   	bernsteinr      sF     
1B9>qsDAJq!rAaCy(1a4/DDDs   ";c                      	  j                     j                  |      S #  Y nxY wt               dz
  }|dk(  rQ d   |d d    d   z
  z  |d d    d   z   z  d d   z  z
  | d    d d    d   z
  z  z    d   z   z  z   z  z   z  z   S |dk(  r/ d   |d d    d   z
  z  | d   d d   z  z
   d   z   z  z   z  z   S |dk(  r d   | d    d   z
  z  z   S |dk(  r d   S t        ||      t	         fdt        |dz         D              S )zEvaluates the Bezier curve given by it's control points, p, at t.
    Note: Uses Horner's rule for cubic and lower order Bezier curves.
    Warning:  Be concerned about numerical stability when using this function
    with high order curves.r      r         c              3   4   K   | ]  }|   |   z    y wr    ).0r   bernps     r   	<genexpr>zbezier_point.<locals>.<genexpr>;   s     6A471Q4<6s   )	large_arcpointlenr   sumr   )r'   r   degr&   s   `  @r   bezier_pointr.      s   	wwqz a&1*C
axtaqtad{Oa1Q4!A$;!AaD&(1qTEAqtad{O+ad2,4 45 56 6 	6 
taqtad{Oa!q1v!$& &' ' 	' 
ta1!o%%	ta 6s1u666s   ! %c                     t               dk(  rD d    d d    d   z
  z  z    d   z   d d   d d   z  z
   d   z   z  d d    d   z
  z   d   f}nt               dk(  r' d   d d   z  z
   d   z   d d    d   z
  z   d   f}nt               dk(  r d    d   z
   d   f}nt               dk(  r }ntt               dz
  }t        |dz         D cg c]>  t        |      t        |z
        z  t         fdt        dz         D              z  @ }}|j	                          |s|ddd   }|rt        |      S |S c c}w )	aq  Converts a tuple of Bezier control points to a tuple of coefficients
    of the expanded polynomial.
    return_poly1d : returns a numpy.poly1d object.  This makes computations
    of derivatives/anti-derivatives and many other operations quite quick.
    numpy_ordering : By default (to accommodate numpy) the coefficients will
    be output in reverse standard order.   r   r    r   r!   c              3   p   K   | ]-  }d |z   z  |   z  t        |      t        |z
        z  z   / yw)Nr   )r%   ijr'   s     r   r(   z$bezier2polynomial.<locals>.<genexpr>X   s?      )J9:R1Q3K!A$#a&3qs8"34)Js   36Nr2   )r+   r   r   r,   reverser
   )r'   numpy_orderingreturn_poly1dcoeffsr   r4   s   `    `r   bezier2polynomialr9   @   s    1v{Q4%!QqTAaD[/)AaD0QqTAadF]QqT)*QqT!A$Y-A$ 
Q1A$1Q4-!A$&QqTAaD[/A$ 
Q1A$qt)A$	Q1 FQJ 1Q3Z! a&#ac("S )J>CAaCj)J &J J ! ! 	"f~M!s   AEc                    t        | t              r| j                  }n| }t        |      dz
  }|dk(  rA|d   |d   dz  |d   z   |d   d|d   z  z   dz  |d   z   |d   |d   z   |d   z   |d   z   f}|S |dk(  r%|d   |d   dz  |d   z   |d   |d   z   |d   z   f}|S |dk(  r|d   |d   |d   z   f}|S t	        d      )zConverts a cubic or lower order Polynomial object (or a sequence of
    coefficients) to a CubicBezier, QuadraticBezier, or Line object as
    appropriate.r   r    r!   r   zOThis function is only implemented for linear, quadratic, and cubic polynomials.)
isinstancer
   r8   r+   AssertionError)polycorderbpointss       r   polynomial2bezierrA   c   s    $KKF1HEzQ41a!A$1!A$(9AaD(@Q4!A$;1%!,. N 
!Q41a!A$!qtad(:; N 
!Q41!% N  A B 	Br   c                 Z    fdg }g } ||| |      \  }}|j                          ||fS )ziUses deCasteljau's recursion to split the Bezier curve at t into two
    Bezier curves of the same order.c                 |   t        |      dk(  r,| j                  |d          |j                  |d          | |fS d gt        |      dz
  z  }| j                  |d          |j                  |d          t        t        |      dz
        D ]  }d|z
  ||   z  |||dz      z  z   ||<     | |||      \  } }| |fS )Nr   r   r2   )r+   appendr   )bpoints_left_bpoints_right_bpoints_t_
new_pointsr3   split_bezier_recursions         r   rJ   z,split_bezier.<locals>.split_bezier_recursion~   s    x=A  !-!!(1+. n,, X!23J  !-!!(2,/3x=1,- J!"R! 4r(1q5/7I I
1J,B~z2-?)M>n,,r   )r5   )r@   r   bpoints_leftbpoints_rightrJ   s       @r   split_bezierrM   {   sB    - LM|]GQG  L-&&r   c                    	 | j                    | j                  d      S #  Y nxY wt        |       dk(  r| d   | d   | d   z   dz  | d   d| d   z  z   | d   z   dz  | d   d| d   z  z   d| d   z  z   | d   z   dz  g| d   d| d   z  z   d| d   z  z   | d   z   dz  | d   d| d   z  z   | d   z   dz  | d   | d   z   dz  | d   gfS t        | d      S )N      ?r0   r   r   r!   r       )r)   splitr+   rM   )r'   s    r   halve_bezierrR      s'   	wws| 1v{1!qtQ1!A$1)=q(@A$1Q4-!AaD&(1Q4/24A$1Q4-!AaD&(1Q4/2A$1Q4-!A$&)AaD1Q4K?AaDBC 	C
 As##s    #c                 F   ddg}t        |       dk(  r| D  cg c]  } | j                   }} |d   d|d   z  z
  d|d   z  z   |d   z
  }t        |      t        kD  r|d   dz  |d   |d   z   |d   z  z
  |d   dz  z   |d   |d   z
  |d   z  z   }|dk\  rmt	        |      }|d   d|d   z  z
  |d   z   }||z   |z  }||z
  |z  }d|cxk  rdk  rn n|j                  |       d|cxk  rdk  rn n|j                  |       |D 	cg c]  }	t        ||	       }
}	t        |
      t        |
      fS t        d      j                         j                  }|t        |      z  }|D 	cg c]  }	t        ||	       }
}	t        |
      t        |
      fS c c} w c c}	w c c}	w )z9returns the minimum and maximum for any real cubic bezierr   r   r0   r    r!   Tr7   )r+   r   absr   r	   rD   r.   minmaxr9   derivr8   r   )r'   local_extremizersadenomdeltasqdeltataur1r2r   local_extremadcoeffss               r   bezier_real_minmaxrc      s   A
1v{QVV!q1v!A$&1-u:%aD!Gqtad{AaD001Q47:adQqTk1Q4=OOEzu+dQqtVmad*GmU*GmU*r:A:%,,R0r:A:%,,R09JKA\!Q/KMK}%s='999  6<<>EEG W--1BCA\!Q'CMC}s=111-   L Ds   FF)Fc                    	 | j                   }| j                         S #  Y nxY wt        |       dk(  r^t        | D cg c]  }|j                   nc c}w c}      \  }}t        | D cg c]  }|j
                   nc c}w c}      \  }}||||fS t        | d      }t	        |      }t        |      }	|j                         }
|	j                         }ddgt        |
dd       z   }ddgt        |dd       z   }|D cg c]
  } ||       nc c}w }}|D cg c]
  } |	|       nc c}w }}t        |      t        |      t        |      t        |      fS )	zreturns the bounding box for the segment in the form
    (xmin, xmax, ymin, ymax).
    Warning: For the non-cubic case this is not particularly efficient.r0   TrT   r   r   c                 "    d| cxk  xr dk  S c S Nr   r   r$   rs    r   <lambda>z%bezier_bounding_box.<locals>.<lambda>       A		 	 r   )	realroots	conditionc                 "    d| cxk  xr dk  S c S rf   r$   rg   s    r   ri   z%bezier_bounding_box.<locals>.<lambda>   rj   r   )r)   bboxr+   rc   r   r   r9   rX   r   rV   rW   )bezblar'   xminxmaxyminymaxr=   xydxdyx_extremizersy_extremizersr   	x_extrema	y_extremas                    r   bezier_bounding_boxr}      sE   mmxxz 3x1}'(=A(=(=>
d'(=A(=(=>
dT4%%S5DT
AT
A	
B	
BFYrT.AC CMFYrT.AC CM,-!1--I-,-!1--I-y>3y>3y>3y>IIs    "A(A< DD+c                     || z
  ||z
  z  S )zP
    INPUT: 2-tuple of cubics (given by control points)
    OUTPUT: boolean
    r$   )rq   rr   rs   rt   s       r   box_arear      s    
 4K$+&&r   c                 H    t        dt        ||      t        | |      z
        S )zreturns the width of the intersection of intervals [a,b] and [c,d]
    (thinking of these as intervals on the real number line)r   )rW   rV   )rZ   br>   ds       r   interval_intersection_widthr      s"     q#a)c!Qi'((r   c                 Z    | \  }}}}|\  }}}}	t        ||||      rt        ||||	      ryy)z`Determines if two rectangles, each input as a tuple
        (xmin, xmax, ymin, ymax), intersect.TF)r   )
box1box2xmin1xmax1ymin1ymax1xmin2xmax2ymin2ymax2s
             r   boxes_intersectr      sB     "&E5%!%E5%"5%>'ueUCr   c                   "    e Zd ZdZd Zd Zd Zy)ApproxSolutionSetzkA class that behaves like a set but treats two elements , x and y, as
    equivalent if abs(x-y) < self.tolc                     || _         y r   )tol)selfr   s     r   __init__zApproxSolutionSet.__init__  s	    r   c                 L    | D ]  }t        ||z
        | j                  k  s y y)NTF)rU   r   )r   ru   rv   s      r   __contains__zApproxSolutionSet.__contains__  s-     	A1q5zDHH$	 r   c                 0    || vr| j                  |       y y r   )rD   )r   pts     r   appaddzApproxSolutionSet.appadd  s    T>KKO r   N)__name__
__module____qualname____doc__r   r   r   r$   r   r   r   r     s    )r   r   c                       e Zd Zd Zy)BPairc                 <    || _         || _        || _        || _        y r   )bez1bez2r   t2)r   r   r   r   r   s        r   r   zBPair.__init__  s    		r   N)r   r   r   r   r$   r   r   r   r     s    r   r   c                    t        t        dt        ||z        t        d      z  z
              }t        | |dd      g}g }d}t	        |      }	|r||k  rg }
d|dz   z  }|D ]  }t        |j                        }t        |j                        }t        ||      s;t        | |k  rt        | |k  rt        | |j                        }||	vr8|	j                  |       |j                  |j                  |j                  f       |D ]x  }|j                  |j                  k(  sL|j                  |j                  k(  s3|j                  |j                  k(  s|j                  |j                  k(  sh|j                  |       z "t        |j                        \  }}|j                  |z
  |j                  |z   }}t        |j                        \  }}|j                  |z
  |j                  |z   }}|
t        ||||      t        ||||      t        ||||      t        ||||      gz  }
 |
}|dz  }|r||k  r||k\  rt!        d      |S )a  INPUT:
    bez1, bez2 = [P0,P1,P2,...PN], [Q0,Q1,Q2,...,PN] defining the two
    Bezier curves to check for intersections between.
    longer_length - the length (or an upper bound) on the longer of the two
    Bezier curves.  Determines the maximum iterations needed together with tol.
    tol - is the smallest distance that two solutions can differ by and still
    be considered distinct solutions.
    OUTPUT: a list of tuples (t,s) in [0,1]x[0,1] such that
        abs(bezier_point(bez1[0],t) - bezier_point(bez2[1],s)) < tol_deC
    Note: This will return exactly one such tuple for each intersection
    (assuming tol_deC is small enough).r   r!   rO   r   zbezier_intersections has reached maximum iterations without terminating... either there's a problem/bug or you can fix by raising the max iterations or lowering tol_deC)intr   r   r   r   r}   r   r   r   r   r.   r   rD   r   removerR   	Exception)r   r   longer_lengthr   tol_deCmaxits	pair_listintersection_listr   approx_point_set	new_pairsr\   pairbbox1bbox2r*   	otherPairc11c12t11t12c21c22t21t22s                            r   bezier_intersectionsr     s>    aGM123q699:;FtT3,-I	A(-
F
	a!e 	=D'		2E'		2Eue,U#g-(E2BW2L(tww7E$44(//6)00$''4771CD &/ 8	99	6 $		Y^^ ; $		Y^^ ; $		Y^^ ;%,,Y78 ".dii!8JS#"&''E/477U?#S!-dii!8JS#"&''E/477U?#S%S#s";"'S#s";"'S#s";"'S#s";"= =I/	=6 		Q? F
@ 	F{ I J 	J r   c                 ^    t        |dd       dk(  sJ |d   |d   k7  sJ t         fd D              st        d       D cg c]
  }||d   z
   }}|d   |d   z
  }t        |      }||z  }|D cg c]  }||z  	 }}|D cg c]  }|j                   }	}t        |	      }
t        t        |
            }|D cg c]  }|j                   }}g }t        |      D ]5  }t        ||      }d|cxk  r|k  sn ||z  }|j                  ||f       7 |S c c}w c c}w c c}w c c}w )zDReturns tuples (t1,t2) such that bezier.point(t1) ~= line.point(t2).Nr!   r   r   c              3   .   K   | ]  }|d    k7    yw)r   Nr$   )r%   r'   beziers     r   r(   z/bezier_by_line_intersections.<locals>.<genexpr>\  s     .!qF1I~.s   zdbezier is nodal, use bezier_by_line_intersection(bezier[0], line) instead for a bool to be returned.)r+   any
ValueErrorrU   r   r9   listr   r   setr.   rD   )r   linezshifted_beziershifted_line_endline_lengthrotation_matrixtransformed_bezierr'   transformed_bezier_imagcoeffs_yroots_ytransformed_bezier_realr   bez_txvalline_ts   `                r   bezier_by_line_intersectionsr   S  sm    tAw<17d1g.v.. > ? 	?
 ,22aa$q'k2N2Awa(&'K ""22O5CD/!+DD 0BB!qvvBB !89H;x()G/AB!qvvBBW 63U;##+%F$$eV_5	6
 + 3 E C Cs   D5D D%?D*N)TF):0yE>r   )&r   
__future__r   r   r   mathr   r   r   r   r	   numpyr
   	polytoolsr   r   r   r   	constantsr   r   r   r.   r9   rA   rM   rR   rc   r}   r   r   r   r   r   objectr   r   r   r$   r   r   <module>r      s   2 A @ 2 2  : 9 $
$E7F F0'2$*2:J>')	 "F 6r$r   