
    Ogd<                    n   U d dl mZ d dlmZmZmZmZmZ d dlZd dl	m
Z
mZ d dlZd dlmZmZmZmZmZmZmZmZmZ d dlZg dZdZ G d d	e      Zdd
Z G d de
      Z G d d      Z	 d	 	 	 	 	 ddZ	 d	 	 	 	 	 ddZ ddZ!eee"e"e"f   ef   Z#de$d<    G d d      Z% G d de%      Z& G d de%      Z'y)    )annotations)IterableTupleIteratorSequenceDictN)Protocol	TypeAlias)	Vec2Vec3UVecNULLVECintersection_line_line_2dBoundingBox2dintersection_line_line_3dBoundingBoxAbstractBoundingBox)ConstructionPolylineApproxParamTintersect_polylines_2dintersect_polylines_3dg&.>c                      e Zd ZdZdef	 	 	 	 	 ddZddZddZ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Zy)r   a  Construction tool for 3D polylines.

    A polyline construction tool to measure, interpolate and divide anything
    that can be approximated or flattened into vertices.
    This is an immutable data structure which supports the :class:`Sequence`
    interface.

    Args:
        vertices: iterable of polyline vertices
        close: ``True`` to close the polyline (first vertex == last vertex)
        rel_tol: relative tolerance for floating point comparisons

    Example to measure or divide a SPLINE entity::

        import ezdxf
        from ezdxf.math import ConstructionPolyline

        doc = ezdxf.readfile("your.dxf")
        msp = doc.modelspace()
        spline = msp.query("SPLINE").first
        if spline is not None:
            polyline = ConstructionPolyline(spline.flattening(0.01))
            print(f"Entity {spline} has an approximated length of {polyline.length}")
            # get dividing points with a distance of 1.0 drawing unit to each other
            points = list(polyline.divide_by_length(1.0))

    Fc                
   t        |      | _        t        j                  |      }|| _        |rEt        |      dkD  r7|d   j                  |d   | j                        s|j                  |d          t        |      | _        y )N   r   rel_tol)	float_rel_tolr   list	_verticesleniscloseappend
_distances)selfverticescloser   v3lists        X/var/www/html/public_html/myphp/venv/lib/python3.12/site-packages/ezdxf/math/polyline.py__init__zConstructionPolyline.__init__F   sl     g!YYx0%+S[1_!9$$VBZ$GfQi('1&'9    c                ,    t        | j                        S )z	len(self))r"   r!   r&   s    r*   __len__zConstructionPolyline.__len__U   s    4>>""r,   c                ,    t        | j                        S )z
iter(self))iterr!   r.   s    r*   __iter__zConstructionPolyline.__iter__Y   s    DNN##r,   c                    t        |t              r| j                  |   S | j                  | j                  |   | j                        S )zvertex = self[item]r   )
isinstanceintr!   	__class__r   )r&   items     r*   __getitem__z ConstructionPolyline.__getitem__]   s;    dC >>$''>>$.."6>NNr,   c                :    | j                   r| j                   d   S y)z+Returns the overall length of the polyline.r           )r%   r.   s    r*   lengthzConstructionPolyline.lengthd   s     ????2&&r,   c                    t        | j                        dkD  r7| j                  d   j                  | j                  d   | j                        S y)zZReturns ``True`` if the polyline is closed
        (first vertex == last vertex).
        r   r   r   r   F)r"   r!   r#   r   r.   s    r*   	is_closedzConstructionPolyline.is_closedk   sM    
 t~~">>!$,,r"DMM -   r,   c                    | j                   }|st        d      | j                  }|dk(  rdd|d   fS ||dz
     }||   }||   }|||z
  |fS )zReturns the tuple (distance from start, distance from previous vertex,
        vertex). All distances measured along the polyline.
        zempty polyliner   r:      )r!   
ValueErrorr%   )r&   indexr'   	distancesprev_distancecurrent_distancevertexs          r*   datazConstructionPolyline.datav   sr     >>-..OO	A:Xa[((!%!),$U+%!1M!A6IIr,   c                ~    |dk  ry|| j                   k\  rt        dt        |       dz
        S | j                  |      S )zReturns the data index of the exact or next data entry for the given
        `distance`. Returns the index of last entry if `distance` > :attr:`length`.

        r:   r   r?   )r;   maxr"   	_index_atr&   distances     r*   index_atzConstructionPolyline.index_at   s>    
 s?t{{"q#d)a-((~~h''r,   c                B    t        j                  | j                  |      S N)bisectbisect_leftr%   rJ   s     r*   rI   zConstructionPolyline._index_at   s    !!$//8<<r,   c                    |dk  s|| j                   kD  rt        d      t        | j                        dk  rt        d      | j	                  |      S )zhReturns the interpolated vertex at the given `distance` from the
        start of the polyline.
        r:   zdistance out of ranger   %not enough vertices for interpolation)r;   r@   r"   r!   
_vertex_atrJ   s     r*   	vertex_atzConstructionPolyline.vertex_at   sN     c>X3455t~~"DEEx((r,   c                ,   | j                   }| j                  }| j                  |      }|dk(  r|d   S |dz
  }||   }||   }|dkD  r||k(  r|dz  }||   }|dkD  r||k(  r||k(  rt        d      ||z
  ||z
  z  }||   j	                  ||   |      S )Nr   r?   zinternal interpolation error)factor)r!   r%   rI   ArithmeticErrorlerp)	r&   rK   r'   rB   index1index0	distance1	distance0rV   s	            r*   rS   zConstructionPolyline._vertex_at   s    >>OO	)Q;A;!f%	f%	qjY)3aKF!&)I qjY)3 	!!"@AAY&9y+@A$$Xf%5f$EEr,   c              #     K   |dk  rt        d|       | j                  }t        j                  d| j                  |      D ]  } ||        yw)zReturns `count` interpolated vertices along the polyline.
        Argument `count` has to be greater than 2 and the start- and end
        vertices are always included.

        r   zinvalid count: r:   N)r@   rS   nplinspacer;   )r&   countrT   rK   s       r*   dividezConstructionPolyline.divide   sU      19ug677OO	Ce< 	&HH%%	&s   AAc              #  V  K   |dk  rt        d|       t        | j                        dk  rt        d      | j                  }| j                  }d}t
        }||k  r ||      }| ||z  }||k  r|r1|j                  | j                  d         s| j                  d    yyyw)a  Returns interpolated vertices along the polyline. Each vertex has a
        fix distance `length` from its predecessor. Yields the last vertex if
        argument `force_last` is ``True`` even if the last distance is not equal
        to `length`.

        r:   zinvalid length: r   rR   r   N)r@   r"   r!   r;   rS   r   r#   )r&   r;   
force_lasttotal_lengthrT   rK   rE   s          r*   divide_by_lengthz%ConstructionPolyline.divide_by_length   s      S=/x899t~~"DEE"kkOO	,&x(FLH ,&
 fnnT^^B-?@..$$ A:s   A2B)54B)N)r'   zIterable[UVec]r(   boolr   r   )returnr5   )rg   Iterator[Vec3]rg   r   )rg   rf   )rA   r5   rg   ztuple[float, float, Vec3])rK   r   rg   r5   )rK   r   rg   r   )r`   r5   rg   rh   )F)r;   r   rc   rf   rg   rh   )__name__
__module____qualname____doc__REL_TOLr+   r/   r2   r8   propertyr;   r=   rF   rL   rI   rT   rS   ra   re    r,   r*   r   r   )   s    >  	: : : 	:#$O    J 	(=)F(
& 16%%)-%	%r,   r   c                    d}g }t               }| D ]=  }|r&||z
  }||j                  z  }|j                  |       n|j                  |       |}? |S )Nr:   )r   	magnituder$   )r'   current_stationrB   prev_vertexrE   distant_vecs         r*   r%   r%      sh     OI&K  ;.K{444O_-_- r,   c                      e Zd ZddZy)SupportsPointMethodc                     y rN   rp   )r&   ts     r*   pointzSupportsPointMethod.point   s    r,   N)ry   r   rg   r   )rj   rk   rl   rz   rp   r,   r*   rw   rw      s    r,   rw   c                  ^    e Zd ZdZddd	 	 	 	 	 ddZedd       Zedd       ZddZdd	Z	y
)r   a9  Approximation tool for parametrized curves.

    - approximate parameter `t` for a given distance from the start of the curve
    - approximate the distance for a given parameter `t` from the start of the curve

    These approximations can be applied to all parametrized curves which provide
    a :meth:`point` method, like :class:`Bezier4P`, :class:`Bezier3P` and
    :class:`BSpline`.

    The approximation is based on equally spaced parameters from 0 to `max_t`
    for a given segment count.
    The :meth:`flattening` method can not be used for the curve approximation,
    because the required parameter `t` is not logged by the flattening process.

    Args:
        curve: curve object, requires a method :meth:`point`
        max_t: the max. parameter value
        segments: count of approximation segments

    g      ?d   )max_tsegmentsc          	         t        d      sJ |dkD  sJ t        fdt        j                  d||dz         D              | _        || _        ||z  | _        y )Nrz   r   c              3  @   K   | ]  }j                  |        y wrN   )rz   ).0ry   curves     r*   	<genexpr>z(ApproxParamT.__init__.<locals>.<genexpr>  s      .
 EKKN.
s   r:   r?   )hasattrr   r^   r_   	_polyline_max_t_step)r&   r   r}   r~   s    `  r*   r+   zApproxParamT.__init__  s`     ug&&&!||- .
$&KKUHqL$I.
 
 X%
r,   c                    | j                   S rN   )r   r.   s    r*   r}   zApproxParamT.max_t  s    {{r,   c                    | j                   S rN   )r   r.   s    r*   polylinezApproxParamT.polyline  s    ~~r,   c                   | j                   }||j                  k\  r| j                  S | j                  }|j	                  |      }|j                  |      \  }}}||z  }|dkD  r||||z
  z  |z  z  }t        | j                  |      S )z^Approximate parameter t for the given `distance` from the start of
        the curve.
        g-q=)r   r;   r   r   rL   rF   min)	r&   rK   polyt_stepistationd0_ry   s	            r*   param_tzApproxParamT.param_t  s     ~~t{{";;MM(#1QQJ:7X-.33A4;;""r,   c                    |dk  ry| j                   }|| j                  k\  r|j                  S | j                  }t	        ||z        dz   }|j                  |      \  }}}||||z  |z
  z  |z  z
  S )zdApproximate the distance from the start of the curve to the point
        `t` on the curve.
        r:   r?   )r   r   r;   r   r5   rF   )r&   ry   r   steprA   r   r   r   s           r*   rK   zApproxParamT.distance-  sz     8~~;;zzAH!5)Qte|a/04777r,   N)r   rw   r}   r   r~   r5   ri   )rg   r   )rK   r   )ry   r   rg   r   )
rj   rk   rl   rm   r+   ro   r}   r   r   rK   rp   r,   r*   r   r      sb    2 &"& 	&
 &    # 8r,   r   c                T    t        | ||      }|j                          |j                  S )aV  Returns the intersection points for two polylines as list of :class:`Vec2`
    objects, the list is empty if no intersection points exist.
    Does not return self intersection points of `p1` or `p2`.
    Duplicate intersection points are removed from the result list, but the list
    does not have a particular order! You can sort the result list by
    :code:`result.sort()` to introduce an order.

    Args:
        p1: first polyline as sequence of :class:`Vec2` objects
        p2: second polyline as sequence of :class:`Vec2` objects
        abs_tol: absolute tolerance for comparisons

    )_PolylineIntersection2dexecuteintersectionsp1p2abs_tol	intersects       r*   r   r   =  *      (B8I"""r,   c                T    t        | ||      }|j                          |j                  S )aV  Returns the intersection points for two polylines as list of :class:`Vec3`
    objects, the list is empty if no intersection points exist.
    Does not return self intersection points of `p1` or `p2`.
    Duplicate intersection points are removed from the result list, but the list
    does not have a particular order! You can sort the result list by
    :code:`result.sort()` to introduce an order.

    Args:
        p1: first polyline as sequence of :class:`Vec3` objects
        p2: second polyline as sequence of :class:`Vec3` objects
        abs_tol: absolute tolerance for comparisons

    )_PolylineIntersection3dr   r   r   s       r*   r   r   R  r   r,   c                    | |z   dz  }| |||fS )Nr   rp   )abms      r*   ra   ra   g  s    	
Q1AaA:r,   r
   TCachec                      e Zd ZU ded<   ded<   ddZej                  dd       Zej                  dd       ZddZ	ddZ
dd	Zy
)_PolylineIntersectionr   r   r   c                    i | _         y rN   )
bbox_cacher.   s    r*   r+   z_PolylineIntersection.__init__s  s     #%r,   c                     y rN   rp   r&   pointss     r*   bboxz_PolylineIntersection.bboxx      r,   c                     y rN   rp   )r&   s1e1s2e2s        r*   line_intersectionz'_PolylineIntersection.line_intersection|  r   r,   c                    t        | j                        }t        | j                        }|dk  s|dk  ry | j                  d|dz
  d|dz
         y )Nr   r   r?   )r"   r   r   r   )r&   l1l2s      r*   r   z_PolylineIntersection.execute  sF    dgg,dgg,6R!Vq"q&!R!V,r,   c                ^   |dz  }|dz  }||z
  dk  s||z
  dk  ry| j                   }d||f}|j                  |      }|#| j                  | j                  ||       }|||<   d||f}|j                  |      }	|	#| j                  | j                  ||       }	|	||<   |j                  |	      S )Nr?   r   F)r   getr   r   r   has_overlap)
r&   r   r   r   r   cachekey1bbox1key2bbox2s
             r*   overlapz_PolylineIntersection.overlap  s    
a
a 7Q;"r'A+2r{		$=IIdggbn-EE$K2r{		$=IIdggbn-EE$K  ''r,   c                   ||kD  r||kD  sJ ||z
  dk(  r||z
  dk(  r| j                  ||||       y t        ||      \  }}}}t        ||      \  }	}
}}| j                  |||	|
      r| j                  |||	|
       | j                  ||||      r| j                  ||||       | j                  |||	|
      r| j                  |||	|
       | j                  ||||      r| j                  ||||       y y )Nr?   )r   ra   r   r   )r&   r   r   r   r   s1_ae1_bs1_ce1_ds2_ae2_bs2_ce2_ds                r*   r   z_PolylineIntersection.intersect  s    Bw27""7a<BGqL""2r2r2!'BdD$!'BdD$<<dD$/NN4tT2<<dD$/NN4tT2<<dD$/NN4tT2<<dD$/NN4tT2 0r,   N)rg   Noner   r   rg   r   
r   r5   r   r5   r   r5   r   r5   rg   r   )
r   r5   r   r5   r   r5   r   r5   rg   rf   )rj   rk   rl   __annotations__r+   abcabstractmethodr   r   r   r   r   rp   r,   r*   r   r   o  sT    LL%
 	  	 -(,3r,   r   c                  2     e Zd Zdd fdZddZddZ xZS )r   c                Z    t         |           || _        || _        g | _        || _        y rN   superr+   r   r   r   r   r&   r   r   r   r6   s       r*   r+   z _PolylineIntersection2d.__init__  +    )+r,   c                    t        |      S rN   )r   r   s     r*   r   z_PolylineIntersection2d.bbox  s    V$$r,   c                .     j                   |    j                   |   f} j                  |    j                  |   f}t        ||d j                        <t	         fd j
                  D              s j
                  j                         y y y )NFvirtualr   c              3  X   K   | ]!  }j                  |j                          # yw)r   Nr#   r   r   ippr&   s     r*   r   z<_PolylineIntersection2d.line_intersection.<locals>.<genexpr>  '      %
46AIIb$,,I/%
   '*)r   r   r   r   anyr   r$   r&   r   r   r   r   line1line2r   s   `      @r*   r   z)_PolylineIntersection2d.line_intersection      TWWR[(TWWR[(%5%
 = %
:>:L:L%
 "
 %%a("
=r,   g|=)r   Sequence[Vec2]r   r   r   r   rj   rk   rl   r+   r   r   __classcell__r6   s   @r*   r   r     s    %	)r,   r   c                  2     e Zd Zdd fdZddZddZ xZS )r   c                Z    t         |           || _        || _        g | _        || _        y rN   r   r   s       r*   r+   z _PolylineIntersection3d.__init__  r   r,   c                    t        |      S rN   )r   r   s     r*   r   z_PolylineIntersection3d.bbox  s    6""r,   c                .     j                   |    j                   |   f} j                  |    j                  |   f}t        ||d j                        <t	         fd j
                  D              s j
                  j                         y y y )NFr   c              3  X   K   | ]!  }j                  |j                          # ywr   r   r   s     r*   r   z<_PolylineIntersection3d.line_intersection.<locals>.<genexpr>  r   r   )r   r   r   r   r   r   r$   r   s   `      @r*   r   z)_PolylineIntersection3d.line_intersection  r   r,   r   )r   Sequence[Vec3]r   r   r   r   r   r   s   @r*   r   r     s    #	)r,   r   )r'   zIterable[Vec3]rg   zlist[float]r   )r   r   r   r   rg   z
list[Vec2])r   r   r   r   rg   z
list[Vec3])r   r5   r   r5   rg   ztuple[int, int, int, int])(
__future__r   typingr   r   r   r   r   r   typing_extensionsr	   r
   numpyr^   
ezdxf.mathr   r   r   r   r   r   r   r   r   rO   __all__rn   r   r%   rw   r   r   r   ra   r5   r   r   r   r   r   rp   r,   r*   <module>r      s    #   1 
 
 
  o%8 o%d ( 
J8 J8\ 5:##*##, 5:##*##*
 sC}-/BBC	 C=3 =3@)3 ).)3 )r,   