
    'j                       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
 d dlmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZ g dZ	 dddZddd ej        d fddZ	 dddZdddZ 	 ddd"Z!ddd&Z"	 ddd)Z#	 	 	 	 	 ddd-Z$	 	 	 ddd0Z% G d1 d2e
          Z&	 	 ddd7Z' ed d           d fdd;Z(dddAZ)	 dddDZ*dddFZ+	 dddLZ,	 	 dddRZ- ed d d            edd d            eddd            ed dd            ed d d           edd d           eddd           ed dd          gZ. edSdSdS           edTdSdS           edTdTdS           edSdTdS           edSdSdT           edTdSdT           edTdTdT           edSdTdT          gZ/g dUg dVg dWg dXg dYg dZgZ0ddd]Z1	 ddd`Z2ddbZ3ddeZ4d*dddBd	dBdfddjZ5	 	 	 	 ddBdlddoZ6	 	 	 	 ddBdlddqZ7dBdBd	drdduZ8	 	 	 ddd|Z9	 ddd~Z:	 ddBdBd	drddZ;	 	 	 ddBdlddZ<	 	 	 	 ddBdlddZ=ej        dfd	dlddZ>	 ddBdddZ?dMdddd*ej        fdBdlddZ@ddZAddZBddZCefddZDefddZEddZFddZGddZHddZIddZJ	 dddZKdBdBdBdrddZLdS )    )annotations)IterableSequenceIteratorCallableOptionalN)IntEnum)Vec2Vec3UVecMatrix44global_bspline_interpolationEulerSpiralarc_angle_span_radNULLVECZ_AXISX_AXISUCSintersection_ray_ray_3d)MeshVertexMergerMeshTransformer)"circleellipseeuler_spiralsquarebox
open_arrowarrow2ngonstargearturtle	translaterotatescaleclose_polygonhelixcubeextrudeextrude_twist_scalesweepcylindercylinder_2pfrom_profiles_linearfrom_profiles_splinespline_interpolationspline_interpolated_profilesconecone_2protation_formspheretorusreference_frame_zreference_frame_extmake_next_reference_frame   Fcountintradiusfloat	elevationcloseboolreturnIterable[Vec3]c              #  (  K   t          |          }t          j        | z  }d}t          |           D ]H}t          j        |          |z  }t          j        |          |z  }t          |||          V  ||z  }I|rt          |d|          V  dS dS )a  Create polygon vertices for a `circle <https://en.wikipedia.org/wiki/Circle>`_
    with the given `radius` and approximated by `count` vertices, `elevation`
    is the z-axis for all vertices.

    Args:
        count: count of polygon vertices
        radius: circle radius
        elevation: z-axis for all vertices
        close: yields first vertex also as last vertex if ``True``.

    Returns:
        vertices in counter-clockwise orientation as :class:`~ezdxf.math.Vec3`
        objects

            r   N)r>   mathtaurangecossinr   )	r;   r=   r?   r@   deltaalphaindexxys	            L/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/render/forms.pyr   r   >   s      $ 6]]FHuEEu  HUOOf$HUOOf$1a##### )61i((((((() )    rxrystart_param	end_paramc              #  p  K   t          |          }t          |          }t          |          }t          |          }t          |           } ||z
  | dz
  z  }t          j        }t          j        }t          |           D ]5}	||	|z  z   }
t           ||
          |z   ||
          |z  |          V  6dS )u  Create polygon vertices for an `ellipse <https://en.wikipedia.org/wiki/Ellipse>`_
    with given `rx` as x-axis radius and `ry` as y-axis radius approximated by
    `count` vertices, `elevation` is the z-axis for all vertices.
    The ellipse goes from `start_param` to `end_param` in counter clockwise
    orientation.

    Args:
        count: count of polygon vertices
        rx: ellipse x-axis radius
        ry: ellipse y-axis radius
        start_param: start of ellipse in range [0, 2π]
        end_param: end of ellipse in range [0, 2π]
        elevation: z-axis for all vertices

    Returns:
        vertices in counter clockwise orientation as :class:`~ezdxf.math.Vec3`
        objects

    r:   N)r>   r<   rF   rI   rJ   rH   r   )r;   rR   rS   rT   rU   r?   rK   rI   rJ   paramrL   s              rP   r   r   ]   s      6 
rB	rB$$Ki  IJJE$3E
(C
(Cu @ @eem+33u::?CCJJOY??????@ @rQ   length	curvaturec              #     K   t          |          }|                    || dz
            D ]}|                    |          V  dS )a  Create polygon vertices for an `euler spiral <https://en.wikipedia.org/wiki/Euler_spiral>`_
    of a given `length` and radius of curvature. This is a parametric curve,
    which always starts at the origin (0, 0).

    Args:
        count: count of polygon vertices
        length: length of curve in drawing units
        curvature: radius of curvature
        elevation: z-axis for all vertices

    Returns:
        vertices as :class:`~ezdxf.math.Vec3` objects

    )rY   r:   )zN)r   approximatereplace)r;   rX   rY   r?   spiralvertexs         rP   r   r      sb      " 9---F$$VUQY77 * *nnyn))))))* *rQ         ?sizetuple[Vec3, Vec3, Vec3, Vec3]c                   |rG| dz  }t          | |           t          ||           t          ||          t          | |          fS t          dd          t          | d          t          | |           t          d|           fS )zReturns 4 vertices for a square with a side length of the given `size`.
    The center of the square in (0, 0) if `center` is ``True`` otherwise
    the lower left corner is (0, 0), upper right corner is (`size`, `size`).
           @r   r   )ra   centeras      rP   r   r      s~    
  J3JQB||T!aR[[$q!**dA2qkkAAAqzz4a==$tT*:*:DDMMIIrQ   sxsyc                   |rL| dz  }|dz  }t          | |           t          ||           t          ||          t          | |          fS t          dd          t          | d          t          | |          t          d|          fS )zReturns 4 vertices for a box with a width of `sx` by and a height of
    `sy`. The center of the box in (0, 0) if `center` is ``True`` otherwise
    the lower left corner is (0, 0), upper right corner is (`sx`, `sy`).
    rd   r   re   )rh   ri   rf   rg   bs        rP   r   r      s      BHHQB||T!aR[[$q!**dA2qkkAAAqzz4A;;Rd1bkkAArQ         >@angletuple[Vec3, Vec3, Vec3]c                    t          j        t          j        |dz                      | z  }t          |  |          t          dd          t          |  |           fS )aF  Returns 3 vertices for an open arrow `<` with a length of the given
    `size`, argument `angle` defines the enclosing angle in degrees.
    Vertex order: upward end vertex, tip (0, 0) , downward end vertex (counter-
    clockwise order)

    Args:
        size: length of arrow
        angle: enclosing angle in degrees

    rd   r   )rF   rJ   radiansr   )ra   rm   hs      rP   r   r      sQ     	eck**++d2Aq>>41::tTEA266rQ        F@betac                6   t          j        t          j        |dz                      | z  }t          j        t          j        |                    |z  }t	          |  |          t	          dd          t	          |  |           t	          |  |z   d          fS )av  Returns 4 vertices for an arrow with a length of the given `size`, and
    an enclosing `angle` in degrees and a slanted back side defined by angle
    `beta`::

                    ****
                ****  *
            ****     *
        **** angle   X********************
            ****     * +beta
                ****  *
                    ****

                    ****
                ****    *
            ****         *
        **** angle        X***************
            ****         * -beta
                ****    *
                    ****

    Vertex order: upward end vertex, tip (0, 0), downward end vertex, bottom
    vertex `X` (anti clockwise order).

    Bottom vertex `X` is also the connection point to a continuation line.

    Args:
        size: length of arrow
        angle: enclosing angle in degrees
        beta: angle if back side in degrees

    rd   r   )rF   rJ   rp   tanr   )ra   rm   rs   rq   	back_steps        rP   r   r      s    D 	eck**++d2Ad++,,q0IdUAQ

dUQBdUY""	 rQ   rE   Optional[float]rotationc              #    K   | dk     rt          d          |=|dk    rt          d          |dz  t          j        t          j        | z            z  }n'||dk    rt          d          nt          d          t          j        | z  }|}d}t          j        }	t          j        }
t          |           D ]8}t          | |	|          z  | |
|          z  |          }||}|V  ||z  }9|r|V  dS dS )	aW  Returns the corner vertices of a `regular polygon <https://en.wikipedia.org/wiki/Regular_polygon>`_.
    The polygon size is determined by the edge `length` or the circum `radius`
    argument. If both are given `length` has the higher priority.

    Args:
        count: count of polygon corners >= 3
        length: length of polygon side
        radius: circum radius
        rotation: rotation angle in radians
        elevation: z-axis for all vertices
        close: yields first vertex also as last vertex if ``True``.

    Returns:
        vertices as :class:`~ezdxf.math.Vec3` objects

       *Argument `count` has to be greater than 2.NrE   z+Argument `length` has to be greater than 0.rd   +Argument `radius` has to be greater than 0.z'Argument `length` or `radius` required.)
ValueErrorrF   rJ   pirG   rI   rH   r   )r;   rX   r=   rx   r?   r@   rK   rm   firstrI   rJ   _vs                rP   r   r      s3     0 qyyEFFFS==JKKK#5 9 99		S==JKKK  BCCCHuEEE
(C
(C5\\  ##e**$fss5zz&99EE=E  rQ   r1r2c              #  P  K   | dk     rt          d          |dk    rt          d          |dk    rt          d          t          | |||d          }t          | |t          j        | z  |z   |d          }d}t	          ||          D ]\  }	}
||	}|	V  |
V  |r|V  dS dS )	ae  Returns the corner vertices for a `star shape <https://en.wikipedia.org/wiki/Star_polygon>`_.

    The shape has `count` spikes, `r1` defines the radius of the "outer"
    vertices and `r2` defines the radius of the "inner" vertices,
    but this does not mean that `r1` has to be greater than `r2`.

    Args:
        count: spike count >= 3
        r1: radius 1
        r2: radius 2
        rotation: rotation angle in radians
        elevation: z-axis for all vertices
        close: yields first vertex also as last vertex if ``True``.

    Returns:
        vertices as :class:`~ezdxf.math.Vec3` objects

    rz   r{   rE   z'Argument `r1` has to be greater than 0.z'Argument `r2` has to be greater than 0.F)r=   rx   r?   r@   N)r}   r   rF   r~   zip)r;   r   r   rx   r?   r@   corners1corners2r   s1s2s              rP   r    r    %  s      4 qyyEFFF	SyyBCCC	SyyBCCCb8y  H 58+  H Eh))  B=E  rQ   c                      e Zd ZdZdZdZdZdS )_Gearr   r:      rz   N)__name__
__module____qualname__	TOP_STARTTOP_ENDBOTTOM_START
BOTTOM_END rQ   rP   r   r   [  s"        IGLJJJrQ   r   	top_widthbottom_widthheightoutside_radiusc              #    K   | dk     rt          d          |dk    rt          d          |dk    rt          d          |dk    rt          d          |dk    rt          d          ||k    rt          d          ||z
  }t          j        |dz  |z            }t          j        |dz  |z            }	|	|z
  dz  }
t          j        | |	z  z
  | z  }| dz  }t          j        }d	}t          j        }t          j        }t          d
| z            D ]}|t          j        k    s|t          j	        k    r|}n|}t          | ||          z  | ||          z  |          }|t          j        k    r||z  }nA|t          j	        k    r||
z  }n+|t          j        k    r||z  }n|t          j        k    r||
z  }||}|V  |dz  }|t          j        k    rt          j        }|r|V  d	S d	S )a  Returns the corner vertices of a `gear shape <https://en.wikipedia.org/wiki/Gear>`_
    (cogwheel).

    .. warning::

        This function does not create correct gears for mechanical engineering!

    Args:
        count: teeth count >= 3
        top_width: teeth width at outside radius
        bottom_width: teeth width at base radius
        height: teeth height; base radius = outside radius - height
        outside_radius: outside radius
        elevation: z-axis for all vertices
        close: yields first vertex also as last vertex if True.

    Returns:
        vertices in counter clockwise orientation as :class:`~ezdxf.math.Vec3`
        objects

    rz   r{   rE   r|   z*Argument `width` has to be greater than 0.z+Argument `height` has to be greater than 0.z1Argument `height` has to be smaller than `radius`rd   N   r:   )r}   rF   asinrG   r   r   rI   rJ   rH   r   r   r   r   )r;   r   r   r   r   r?   r@   base_radius	alpha_topalpha_bottomalpha_differencers   rm   stater   rI   rJ   r   r=   r   s                       rP   r!   r!   b  sM     < qyyEFFFFGGGCEFFFsEFFF}}FGGGLMMM 6)K	)c/N:;;I9\C/+=>>Ly  Hu|++u4DJEOEE
(C
(C1u9 $ $EO##u'='=#FF F##e**$fss5zz&99EEEO##YEEem##%%EEe(((TMEEe&&&%%E=E
5###OE  rQ   commandsstrIterator[Vec2]c              #    K   |}|V  |                      d          D ]}|                                }|d         dk    r4t          |          dk    r|dz  }<|t          |dd                   z  }W|d         dk    r4t          |          dk    r|dz  }||t          |dd                   z  }|d         dk    rR|dd                              d	          \  }}|t	          t          |          t          |                    z  }|V  |t	          j        |t          |                    z  }|V   dS )
a  Returns the 2D vertices of a polyline created by turtle-graphic like
    commands:

    - ``<length>`` - go <length> units forward in current direction and yield vertex
    - ``r<angle>`` - turn right <angle> in degrees, a missing angle is 90 deg
    - ``l<angle>`` - turn left <angle> in degrees, a missing angle is 90 deg
    - ``@<x>,<y>`` - go relative <x>,<y> and yield vertex

    The command string ``"10 l 10 l 10"`` returns the 4 corner vertices of a
    square with a side length of 10 drawing units.

    Args:
        commands: command string, commands are separated by spaces
        start: starting point, default is (0, 0)
        angle: starting direction, default is 0 deg

     r   lr:   Z   Nr@,)splitstriplenr>   r
   from_deg_angle)r   startrm   cursorcmdrN   rO   s          rP   r"   r"     sG     & F
LLL~~c""  iikkq6S==3xx1}}s122w'Vs]]3xx1}}s122w'Vs]]qrr7==%%DAqd588U1XX...FLLLLd)%s<<<FLLLL% rQ   r   r   r   verticesIterable[UVec]vecr   c              #  @   K   t          |          }| D ]	}||z   V  
dS )zTranslate `vertices` along `vec`, faster than a Matrix44 transformation.

    Args:
        vertices: iterable of vertices
        vec: translation vector

    Returns: yields transformed vertices

    Nre   )r   r   _vecps       rP   r#   r#     s;       99D  Qh rQ   Tdegc                @    |rfd| D             S fd| D             S )a"  Rotate `vertices` about to z-axis at to origin (0, 0), faster than a
    Matrix44 transformation.

    Args:
        vertices: iterable of vertices
        angle: rotation angle
        deg: True if angle in degrees, False if angle in radians

    Returns: yields transformed vertices

    c              3  \   K   | ]&}t          |                                        V  'd S N)r   
rotate_deg.0r   rm   s     rP   	<genexpr>zrotate.<locals>.<genexpr>  s7      <<aQ""5))<<<<<<rQ   c              3  \   K   | ]&}t          |                                        V  'd S r   )r   r$   r   s     rP   r   zrotate.<locals>.<genexpr>  s5      88!Qu%%888888rQ   r   )r   rm   r   s    ` rP   r$   r$     sA      9<<<<8<<<<8888x8888rQ   r`   r`   r`   c              #     K   |\  }}}t          j        |           D ]-}t          |j        |z  |j        |z  |j        |z            V  .dS )zScale `vertices` around the origin (0, 0), faster than a Matrix44
    transformation.

    Args:
        vertices: iterable of vertices
        scaling: scale factors as tuple of floats for x-, y- and z-axis

    Returns: yields scaled vertices

    N)r   generaterN   rO   r[   )r   scalingrh   ri   szr   s         rP   r%   r%     sc       JBB]8$$ 1 1138QS2XqsRx0000001 1rQ   &.>-q=rel_tolabs_tol
list[Vec3]c                    t          |           }|d                             |d         ||          s|                    |d                    |S )zgReturns list of :class:`~ezdxf.math.Vec3`, where the first vertex is
    equal to the last vertex.
    r   )r   r   )listiscloseappend)r   r   r   polygons       rP   r&   r&     sO     x..G1:gbk7GLL #wqz"""NrQ      pitchturns
resolutionIterator[Vec3]c              #  l  K   dt          |d          z  }|s| }t          |t          |          z            }t          |dz             D ]g}||z  }|t          j        z  }	t	          j        |	          | z  }
t	          j        |	          | z  }t          |
|t          |          |z            V  hdS )a  Yields the vertices of a `helix <https://en.wikipedia.org/wiki/Helix>`_.
    The center of the helix is always (0, 0), a positive `pitch` value
    creates a helix along the +z-axis, a negative value along the -z-axis.

    Args:
        radius: helix radius
        pitch: the height of one complete helix turn
        turns: count of turns
        resolution: vertices per turn
        ccw: creates a counter-clockwise turning (right-handed) helix if ``True``

    r`   r:   N)	maxr<   absrH   rF   rG   rI   rJ   r   )r=   r   r   r   ccwsteptotal_step_countrM   trm   rN   rO   s               rP   r'   r'     s      & J***D u53t99,--'!+,, ) )5LDHHUOOf$HUOOf$1aQ%(((((() )rQ   g            ?)r   rz   r   r:   )r:   r         )rz      r   r   )r   r   r   rz   )r   r:   r   r   )r   r   r   r   rf   r   c                z    t                      }| rt          nt          }|                    |t                     |S )a"  Create a `cube <https://en.wikipedia.org/wiki/Cube>`_ as
    :class:`~ezdxf.render.MeshTransformer` object.

    Args:
        center: 'mass' center of cube, ``(0, 0, 0)`` if ``True``, else first
            corner at ``(0, 0, 0)``

    Returns: :class:`~ezdxf.render.MeshTransformer`

    )r   faces)r   _cube0_vertices_cube_verticesadd_mesh
cube_faces)rf   meshr   s      rP   r(   r(   `  s8     D"(<nHMM8:M666KrQ   profilepathc                   t                      }t          j        |           }|rt          |          }t          j        |          }|r*|                    t          |dd                              |d         }|dd         D ]A}||z
  fd|D             }	t          ||	          D ]}
|                    |
           |	}|}B|r|                    |dd                    t          j        |          S )a  Extrude a `profile` polygon along a `path` polyline, the vertices of
    `profile` should be in counter-clockwise order.
    The sweeping profile will not be rotated at extrusion!

    Args:
        profile: sweeping profile as list of (x, y, z) tuples in
            counter-clockwise order
        path:  extrusion path as list of (x, y, z) tuples
        close: close profile polygon if ``True``
        caps: close hull with top- and bottom faces (ngons)

    Returns: :class:`~ezdxf.render.MeshTransformer`

    Nr   r   r:   c                    g | ]}|z   S r   r   )r   r   translation_vectors     rP   
<listcomp>zextrude.<locals>.<listcomp>  s    OOOs# 22OOOrQ   )	r   r   r   r&   add_facereversed_quad_connection_facesr   from_builder)r   r   r@   capsr   sweeping_profileextrusion_pathstart_pointtarget_pointtarget_profilefacer   s              @rP   r)   r)   q  s(   " Dy)) ;()9::Yt__N 7h/455666 #K&qrr* # #)K7OOOO>NOOO*+;^LL 	  	 DMM$)" -&ss+,,,'---rQ   list[float]c                    d t          | | dd                    D             }t          |          }dg}d}|D ]}||z  }|                    ||z              |S )Nc                >    g | ]\  }}|                     |          S r   )distance)r   v1v2s      rP   r   z)_partial_path_factors.<locals>.<listcomp>  s&    III62rr{{2IIIrQ   r:   rE   )r   sumr   )r   partial_lengthstotal_lengthfactorspartial_sumpls         rP   _partial_path_factorsr    sx    IIStABBx5H5HIIIO''LeGK 3 3r{\12222NrQ   Sequence[Vec3]max_step_sizec                X   | d         g}t          | | dd                    D ]\  }}||z
  }|j        }||k    r[t          t          j        ||z                      }|d|z  z  }t          |dz
            D ]}	||z  }|                    |           |                    |           |S )Nr   r:   r`   )r   	magnituder<   rF   ceilrH   r   )
r   r  new_pathv0r   segment_vecrX   partsr   r   s
             rP   _divide_path_into_stepsr    s     G9HdDH%% 	 	B2g&M!!	&="899::E#+.D519%% $ $d
####OrQ   )twistr%   	step_sizer@   r   quadsr  r%   r  c                  dfd}t                      }	t          j        |           }
|rt          |
          }
|r*|	                    t          |
dd                              t          j        |          }|dk    rt          ||          }t          |          }|d	         |
}|rt          nt          }t          |d
d         |d
d                   D ]V\  }t           ||                              |
                    } |||          D ]}|	                    |           |}W|r|	                    |dd                    t          j        |	          S )a6  Extrude a `profile` polygon along a `path` polyline, the vertices of
    `profile` should be in counter-clockwise order.
    This implementation can scale and twist the sweeping profile along the
    extrusion path. The `path` segment points are fix points, the
    `max_step_size` is used to create intermediate profiles between this
    fix points. The `max_step_size` is adapted for each
    segment to create equally spaced distances.
    The twist angle is the rotation angle in radians and the scale `argument`
    defines the scale factor of the final profile.
    The twist angle and scaling factor of the intermediate profiles will be
    linear interpolated between the start and end values.

    Args:
        profile: sweeping profile as list of (x, y, z) tuples in
            counter-clockwise order
        path:  extrusion path as list of (x, y, z) tuples
        twist: rotate sweeping profile up to the given end rotation angle in
            radians
        scale: scale sweeping profile gradually from 1.0 to given value
        step_size: rough distance between automatically created intermediate
            profiles, the step size is adapted to the distances between the
            path segment points, a value od 0.0 disables creating intermediate
            profiles
        close: close profile polygon if ``True``
        caps: close hull with top- and  bottom faces (ngons)
        quads: use quads for "sweeping" faces if ``True`` else triangles,
            the top and bottom faces are always ngons

    Returns: :class:`~ezdxf.render.MeshTransformer`

    facr>   rB   r   c                    ddz
  | z  z   }	| z  }z
  }|t          j        |          z  }|t          j        |          z  }t          ||dd| |dddd|d|j        |j        |j        dg          S )Nr`   rE   )rF   rI   rJ   r   rN   rO   r[   )
r  current_scalecurrent_rotationtranslationscale_cos_ascale_sin_ar%   r   r   r  s
         rP   matrixz#extrude_twist_scale.<locals>.matrix  s    us{c11 3;"[0#dh/?&@&@@#dh/?&@&@@c3L+sCmSM;=+-	
   	rQ   Nr   rE   r   r:   )r  r>   rB   r   )r   r   r   r&   r   r   r  r  r   _tri_connection_facesr   transform_verticesr   r   )r   r   r  r%   r  r@   r   r  r  r   r   r   r  prev_profileface_generatorfactorr   r   r   r   s     ``              @@rP   r*   r*     s   V         Dy)) ;()9:: 7h/455666Yt__NC0KK#N33G #K#L/4O++:ON #N122$6 D D & &fffVnn??@PQQRR"N<@@ 	  	 DMM$% )l3B3'((('---rQ   r   r   r:   )r   
top_radius
top_centerc          	        ||}t          j        |d          rt          | ||          S t          t	          | |d                    }t          t          t	          | |d          |                    }t          ||gdd|          S )a  Create a `cylinder <https://en.wikipedia.org/wiki/Cylinder>`_ as
    :class:`~ezdxf.render.MeshTransformer` object, the base center is fixed in
    the origin (0, 0, 0).

    Args:
        count: profiles edge count
        radius: radius for bottom profile
        top_radius: radius for top profile, if ``None`` top_radius == radius
        top_center: location vector for the center of the top profile
        caps: close hull with top- and  bottom faces (ngons)

    NrE   )r;   r=   apexTr@   Fr@   r  r   )rF   r   r2   r   r   r#   r.   )r;   r=   r#  r$  r   base_profiletop_profiles          rP   r,   r,     s    ( 
|J$$ A%Z@@@@ufD999::Lyz!F!F!F
SSTTK	{#	   rQ   base_centerc               x   t          |          }t          |          |z
  }|j        rt          d          t          | |dd|j        f|          }	 t          |t          j        |          |          }n'# t          $ r t          |t          |          }Y nw xY w|
                    |j                   |S )aK  Creates a `cylinder <https://en.wikipedia.org/wiki/Cylinder>`_ as
    :class:`~ezdxf.render.MeshTransformer` object from two points,
    `base_center` is the center of the base circle and, `top_center` the center
    of the top circle.

    Args:
        count: cylinder profile edge count
        radius: radius for bottom profile
        base_center: center of base circle
        top_center: center of top circle
        caps: close hull with top- and  bottom faces (ngons)

    Raises:
        ValueError: the cylinder orientation cannot be detected (base center == top center)

    zCcylinder orientation cannot be detected (base center == top center)r   )r$  r   originuyuzr.  uxr0  )r   is_nullr}   r,   r
  r   r   crossZeroDivisionErrorr   	transformr  )	r;   r=   r+  r$  r   r.  headingr   ucss	            rP   r-   r-   (  s    0 +F:'G 
Q
 
 	
 E6q!W5F.GdSSSD8FL$9$9gFFF 8 8 8Fw7778 	NN3:K   $A9 9!BBr(  profilesSequence[Sequence[Vec3]]c                  t                      }|rd | D             } |r(|                    t          | d                              |rt          nt          }t          | | dd                   D ])\  }} |||          D ]}|                    |           *|r|                    | d                    t          j        |          S )aQ  Returns a :class:`~ezdxf.render.MeshTransformer` instance from linear
    connected `profiles`.

    Args:
        profiles: list of profiles
        close: close profile polygon if ``True``
        quads: use quadrilaterals as connection faces if ``True`` else triangles
        caps: close hull with top- and bottom faces (ngons)

    c                ,    g | ]}t          |          S r   )r&   r   r   s     rP   r   z(from_profiles_linear.<locals>.<listcomp>c  s     777M!$$777rQ   r   r:   Nr   )r   r   r   r   r  r   r   r   )	r:  r@   r  r   r   r   p0p1r   s	            rP   r.   r.   P  s    " D 877h777 -hx{++,,,/4O++:ONh--    B"N2r** 	  	 DMM$	  $hrl###'---rQ   rz   chordr   degreemethod	subdividec                    t          |           } t          | ||          }t          |                    t          |           dz
  |z                      S )a  B-spline interpolation, vertices are fit points for the spline
    definition.

    Only method 'uniform', yields vertices at fit points.

    Args:
        vertices: fit points
        degree: degree of B-spline
        method: "uniform", "chord"/"distance", "centripetal"/"sqrt_chord" or
            "arc" calculation method for parameter t
        subdivide: count of sub vertices + 1, e.g. 4 creates 3 sub-vertices

    Returns: list of vertices

    )rB  rC  r:   )segments)r   r   r\   r   )r   rB  rC  rD  splines        rP   r0   r0   o  sR    * H~~H)(6&QQQF""S]]Q->),K"LLMMMrQ   Iterable[list[Vec3]]c              #    K   t          t          d | D                                 dk    rt          d          t          | d                   }g }t          |          D ]4fd| D             }|                    t          ||                     5t          |d                   }t          |          D ]fd|D             V  dS )	a&  Profile interpolation by cubic B-spline interpolation.

    Args:
        profiles: list of profiles
        subdivide: count of interpolated profiles + 1, e.g. 4 creates 3
            sub-profiles between two main profiles (4 face loops)

    Returns: yields profiles as list of vertices

    c              3  4   K   | ]}t          |          V  d S r   )r   r>  s     rP   r   z/spline_interpolated_profiles.<locals>.<genexpr>  s(      ((!s1vv((((((rQ   r:   z/All profiles have to have the same vertex countr   c                     g | ]
}|         S r   r   )r   r   rM   s     rP   r   z0spline_interpolated_profiles.<locals>.<listcomp>  s    444a5444rQ   )rD  c                     g | ]
}|         S r   r   )r   edgeprofile_indexs     rP   r   z0spline_interpolated_profiles.<locals>.<listcomp>  s    555ttM"555rQ   N)r   setr}   rH   r   r0   )r:  rD  vertex_countedgesedge_verticesprofile_countrM   rN  s         @@rP   r1   r1     s      3((x((((())Q..JKKKx{##LE|$$ O O44448444)-9MMMNNNNaMMM}-- 6 65555u55555556 6rQ   c                   t          |           dk    rt          t          | |                    } nt          d          t	          | |||          S )a6  Returns a :class:`~ezdxf.render.MeshTransformer` instance by spline
    interpolation between given `profiles`.
    Requires at least 4 profiles. A `subdivide` value of 4, means, create 4 face
    loops between two profiles, without interpolation two profiles create one
    face loop.

    Args:
        profiles: list of profiles
        subdivide: count of face loops
        close: close profile polygon if ``True``
        quads: use quadrilaterals as connection faces if ``True`` else triangles
        caps: close hull with top- and bottom faces (ngons)

    rz   z1Spline interpolation requires at least 4 profilesr(  )r   r   r1   r}   r.   )r:  rD  r@   r  r   s        rP   r/   r/     sa    , 8}}q4XyIIJJLMMM	   rQ   r&  c               8   t                      }t          t          | |d                    }t          ||dd                   D ]\  }}|                    |||g           |r"|                    t          |                     t          j        |          S )aU  Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as
    :class:`~ezdxf.render.MeshTransformer` object, the base center is fixed in
    the origin (0, 0, 0).

    Args:
        count: edge count of basis_vector
        radius: radius of basis_vector
        apex: tip of the cone
        caps: add a bottom face as ngon if ``True``

    Tr'  r:   N)r   r   r   r   r   r   r   r   )r;   r=   r&  r   r   base_circler@  p2s           rP   r2   r2     s    $ DveV488899Kk;qrr?33 & &Br2tn%%%% -h{++,,,'---rQ   c               x   t          |          }t          |          |z
  }|j        rt          d          t          | |dd|j        f|          }	 t          |t          j        |          |          }n'# t          $ r t          |t          |          }Y nw xY w|
                    |j                   |S )a  Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as
    :class:`~ezdxf.render.MeshTransformer` object from two points, `base_center`
    is the center of the base circle and `apex` as the tip of the cone.

    Args:
        count: edge count of basis_vector
        radius: radius of basis_vector
        base_center: center point of base circle
        apex: tip of the cone
        caps: add a bottom face as ngon if ``True``

    Raises:
        ValueError: the cone orientation cannot be detected (base center == apex)

    z=the cone orientation cannot be detected (base center == apex)r   )r&  r   r-  r1  )r   r3  r}   r2   r
  r   r   r4  r5  r   r6  r  )	r;   r=   r+  r&  r   r.  r7  r   r8  s	            rP   r3   r3     s    . +F4jj6!G 
K
 
 	
 vQ7+<$=DIIID8FL$9$9gFFF 8 8 8Fw7778 	NN3:Kr9  )r:   r   r   axisc                  | dk     rt          d          t          |          | z  }t          j        t	          |          |          }d |D             }|g}t          t          |                     D ]9}t          |                    |                    }|	                    |           :t          |dd|          }	|	S )a`  Returns a :class:`~ezdxf.render.MeshTransformer` instance created by
    rotating a `profile` around an `axis`.

    Args:
        count: count of rotated profiles
        profile: profile to rotate as list of vertices
        angle: rotation angle in radians
        axis: rotation axis
        caps: close hull with start- and end faces (ngons)

    rz   z
count >= 2c                ,    g | ]}t          |          S r   re   r>  s     rP   r   z!rotation_form.<locals>.<listcomp>"  s    (((1tAww(((rQ   FTr(  )r}   r>   r   axis_rotater   rH   r<   r   r  r   r.   )
r;   r   rm   rY  r   rK   mr:  r   r   s
             rP   r4   r4     s    & qyy&&&%LL5 ET$ZZ//A(((((GyH3u:: ! !q++G4455    	  D KrQ      )r  stacksc               j   t                    t          |           t          |          dz  }t          j        t                    z  t          j        t          |          z  t                      dfddfd
dfd	} || dz   d           t          | dz   |dz
            D ]Q}|dz   } |          } |          }	t          j        |z            z  }
t          j        |z            z  }t                    D ]} |||
          } |dz   ||
          } |dz   |	|          } ||	|          }|r                    ||||g           X |dz    |dz             t          j        |dz   z            z            }                    |||g                               |||g                               |||g                               |||g           S ||dz
  d           t          j
                  S )a_  Create a `sphere <https://en.wikipedia.org/wiki/Sphere>`_ as
    :class:`~ezdxf.render.MeshTransformer` object, the center of the sphere is
    always at (0, 0, 0).

    Args:
        count: longitudinal slices
        stacks: latitude slices
        radius: radius of sphere
        quads: use quadrilaterals as faces if ``True`` else triangles

    r   stackr>   rB   c                8    t          j        | z            z  S r   )rF   rI   )ra  	delta_phir=   s    rP   radius_of_stackzsphere.<locals>.radius_of_stackE  s    U!23333rQ   slice_r   r[   r   c                    | z  }t          t          j        |          |z  t          j        |          |z  |          S r   )r   rF   rI   rJ   )re  r   r[   actual_thetadelta_thetas       rP   r_   zsphere.<locals>.vertexH  s=    "V+DH\**Q.0F0F0JANNNrQ   Fc                `   t          j        | z            
z  }|rt          dd
          nt          dd
           } |           }t                    D ]R} |||          } |dz   ||          }|r	                    |||f           :	                    |||f           Sd S Nr   r:   )rF   rJ   r   rH   r   )ra  topr[   
cap_vertexr   re  r   r   rc  r   r=   rd  slicesr_   s           rP   cap_triangleszsphere.<locals>.cap_trianglesL  s    HUY&''&0+.GT!Q'''DAw4G4G
_U##Fmm 	4 	4FA&&B
B**B 4r2z23333z2r23333	4 	4rQ   r:   )rk  r   T)ra  r>   rB   r>   )re  r>   r   r>   r[   r>   rB   r   )F)r>   r<   rF   rG   r~   r   rH   rJ   r   r   r   )r;   r_  r=   r  stacks_2rn  actual_stack
next_stackr   r   z1z2ir   r   v3v4rf   rc  rh  r   rd  rm  r_   s     `               @@@@@@rP   r5   r5   0  s    6]]FZZF6{{aH(U6]]*K%--'ID4 4 4 4 4 4 4O O O O O O
4 
4 
4 
4 
4 
4 
4 
4 
4 
4 
4 M8)a-U++++ xi!mX\:: 0 0!A%
_\**_Z((Xi,.//&8Xi*,--6v 	0 	0A2r""BAr2&&BAr2&&B2r""B 0r2r2.////G#OL3$677HY,*<=>>G 
 r2v.///r2v.///r2v.///r2v.////!	0& M(Q,D))))'---rQ   g?major_countminor_countstart_angle	end_anglec          	        | dk     rt          d          |dk     rt          d          t          j        t          |                    }t          j        t          |                    }|dk     rt          d          |dk     rt          d          ||k    rt          d          t                    t          j        z  |t          j        k    rt          |          t          j        z  }t          |          }t          j        |t          j                  }|| z  d	 t          t          ||d
          t          |dd                    D             }	|	
                                 dk    rfd|	D             }	t                      }
|	}fd|	D             }|s$|r"|
                    t          |                     t          |           D ]:}t          ||          D ]}|
                    |           |}fd|D             };|s|r|
                    |           t!          j        |
          S )aV  Create a `torus <https://en.wikipedia.org/wiki/Torus>`_ as
    :class:`~ezdxf.render.MeshTransformer` object, the center of the torus is
    always at (0, 0, 0). The `major_radius` has to be bigger than the
    `minor_radius`.

    Args:
        major_count: count of circles
        minor_count: count of circle vertices
        major_radius: radius of the circle center
        minor_radius: radius of circle
        start_angle: start angle of torus in radians
        end_angle: end angle of torus in radians
        caps: close hull with start- and end faces (ngons) if the torus is open

    r:   zmajor_count < 1rz   zminor_count < 3r   zmajor_radius is 0zminor_radius is 0zminor_radius >= major_radiusc                D    g | ]}t          |j        d |j                  S )r   )r   rN   rO   )r   r   s     rP   r   ztorus.<locals>.<listcomp>  s8        	QS!QS  rQ   Tr'  r   c                :    g | ]}|                               S r   r$   )r   r   ry  s     rP   r   ztorus.<locals>.<listcomp>  s%    HHHA!((;//HHHrQ   c                :    g | ]}|                               S r   r~  r   r   
step_angles     rP   r   ztorus.<locals>.<listcomp>  s%    @@@A188J''@@@rQ   c                :    g | ]}|                               S r   r~  r  s     rP   r   ztorus.<locals>.<listcomp>  s%    AAAqxx
++AAArQ   )r}   rF   fabsr>   rG   r   r   r#   r   r   reverser   r   r   rH   r   r   r   )rw  rx  major_radiusminor_radiusry  rz  r   
angle_spanclosed_toruscircle_profiler   start_profileend_profiler   r   r  s       `          @rP   r6   r6   z  s   2 Q+,,,Q+,,,9U<0011L9U<0011Ld,---d,---|##7888$$tx/KDH)$$tx/	#K;;J<
DH55Lk)J ;D999q!$$
 
  N THHHHHHHD"M@@@@@@@K /D /h}--...; B B*=+FF 	  	 DMM$#AAAA[AAA %D %m$$$'---rQ   r  r  quadIterator[Sequence[Vec3]]c              #     K   t          |           t          |          k    s
J d            |rt          | |          E d {V  d S t          | |          E d {V  d S )Nzprofiles differ in vertex count)r   r   r  )r  r  r  s      rP   connection_facesr    s       }[!1!11113T111 E)-EEEEEEEEEEE(DDDDDDDDDDDrQ   c              #     K   | d         }|d         }t          | dd          |dd                    D ]\  }}||||fV  |}|}d S rj  r   r  r  v0_prevv1_prevr  r   s         rP   r   r     st       AG!nGmABB'QRR99  Br2w&&&& rQ   c              #     K   | d         }|d         }t          | dd          |dd                    D ]\  }}|||fV  |||fV  |}|}d S rj  r  r  s         rP   r  r    s       AG!nGmABB'QRR99  B'7####r2o	 rQ   r7  r   r.  r   c                J    t          t          j        |           | |          S )a  Returns a reference frame as UCS from the given heading and the
    WCS z-axis as reference "up" direction.
    The z-axis of the reference frame is pointing in heading direction, the
    x-axis is pointing right and the y-axis is pointing upwards.

    The reference frame is used to project vertices in xy-plane
    (construction plane) onto the normal plane of the given heading.

    Use the :func:`reference_frame_ext` if heading is parallel to the WCS
    Z_AXIS.

    Args:
        heading: WCS direction of the reference frame z-axis
        origin: new UCS origin

    Raises:
        ZeroDivisionError: heading is parallel to WCS Z_AXIS

    r/  r0  r.  )r   r   r4  )r7  r.  s     rP   r7   r7     s#    ( &,w''GFCCCCrQ   framec                    	 t          t          j        | j                  t          |          S # t          $ r7 t          | j                            t                    t          |          cY S w xY w)zReference frame calculation if heading vector is parallel to the WCS
    Z_AXIS.

    Args:
        frame: previous reference frame
        origin: new UCS origin

    r  )r2  r0  r.  )r   r   r4  r2  r5  r/  )r  r.  s     rP   r8   r8     sq    Hfl58,,GGGG H H HehnnV,,GGGGGGHs   -0 >A10A1	prev_rays	next_raysc              #  0  K   t          | |          D ]\  }}t          ||          }t          |          }|dk    r|d         V  5|dk    r$|d                             |d                   V  _|d                             |d                   V  d S )Nr:   r   r   r   )r   r   r   lerp)r  r  ray1ray2ipr;   s         rP   _intersect_raysr    s       )Y// ) )
d$T400BA::Q%KKKKaZZQ%**RU######r(--Q(((((() )rQ   start_profilesend_profileslist[Sequence[Vec3]]c           	        | d         g}d t          | |          D             }t          ||dd                    D ]5\  }}|                    t          t          ||                               6|                    |d                    |S )Nr   c                H    g | ]\  }}d  t          ||          D              S )c                    g | ]	\  }}||f
S r   r   )r   r  r   s      rP   r   z5_intersection_profiles.<locals>.<listcomp>.<listcomp>  s     ,,,fb""b,,,rQ   r  )r   r?  r@  s      rP   r   z*_intersection_profiles.<locals>.<listcomp>  sB       B 	-,B,,,  rQ   r:   r   )r   r   r   r  )r  r  r:  raysr  r  s         rP   _intersection_profilesr    s     '5Q&7%8H .,77  D !$D$qrr( 3 3 E E	9_Y	BBCCDDDDOOL$%%%OrQ   c                    	 t          ||          }|j                            | j                  dk     rt          ||j        |j                   }|S # t
          $ r t          | |          cY S w xY w)a  Returns the following reference frame next to the current reference
    `frame`.

    Args:
        frame: the current reference frame
        heading: z-axis direction of the following frame in WCS
        origin: origin of the following reference frame

    r   )r.  r0  r/  )r7   r/  dotr   r0  r5  r8   )r  r7  r.  
next_frames       rP   r9   r9   (  s    	2&w77
 =UX&&**Fz}*-PPPJ 2 2 2"5&111112s   AA A10A1sweeping_pathnext_ref_frame Callable[[UCS, Vec3, Vec3], UCS])tuple[list[list[Vec3]], list[list[Vec3]]]c                   t          j        |          }t          j        |           }g }g }t                      }t          ||dd                    D ]o\  }}	|	|z
   |||          }t          |                    |                    }
|                    |
           |                    fd|
D                        p||fS )Nr:   c                    g | ]}|z   S r   r   )r   r   r7  s     rP   r   z6_make_sweep_start_and_end_profiles.<locals>.<listcomp>M  s    @@@QQ[@@@rQ   )r   r   r   r   points_to_wcsr   )r   r  r  spathreference_profiler  r  	ref_framer.  targetr  r7  s              @rP   "_make_sweep_start_and_end_profilesr  >  s    
 Im$$E	'**NLIeU122Y// B B6/"N9gv>>	Y445FGGHHm,,,@@@@-@@@AAAA<''rQ   c                <    t          t          | |t                     S )a  Returns the intermediate profiles of sweeping a profile along a 3D path
    where the sweeping path defines the final location in the `WCS`.

    The profile is defined in a reference system. The origin of this reference
    system will be moved along the sweeping path where the z-axis of the
    reference system is pointing into the moving direction.

    Returns the start-, end- and all intermediate profiles along the sweeping
    path.

    )r  r  r9   )r   r  s     rP   sweep_profiler  Q  s&     "	+]$=

 

 rQ   c                    |rt          |           } g }t          t          | |t                     D ]/\  }}|                    |           |                    |           0|S r   )r&   r   r  r9   r   )r   r  r@   r:  speps         rP   debug_sweep_profilesr  g  sy    
  )((%'H	+]$=

 

  B
 	OrQ   c               H    t          | |          }t          ||||          S )ae  Returns the mesh from sweeping a profile along a 3D path, where the
    sweeping path defines the final location in the `WCS`.

    The profile is defined in a reference system. The origin of this reference
    system will be moved along the sweeping path where the z-axis of the
    reference system is pointing into the moving direction.

    Returns the mesh as :class:`ezdxf.render.MeshTransformer` object.

    Args:
        profile: sweeping profile defined in the reference system as
            iterable of (x, y, z) coordinates in counter-clockwise order
        sweeping_path: the sweeping path defined in the WCS as iterable of
            (x, y, z) coordinates
        close: close sweeping profile if ``True``
        quads: use quadrilaterals as connection faces if ``True`` else triangles
        caps: close hull with top- and bottom faces (ngons)

    r(  )r  r.   )r   r  r@   r  r   r:  s         rP   r+   r+   y  s6    6 Wm44H	   rQ   )r:   r   F)
r;   r<   r=   r>   r?   r>   r@   rA   rB   rC   )r;   r<   rR   r>   rS   r>   rT   r>   rU   r>   r?   r>   rB   rC   )r:   r:   r   )
r;   r<   rX   r>   rY   r>   r?   r>   rB   rC   )r`   F)ra   r>   rB   rb   )r`   r`   F)rh   r>   ri   r>   rB   rb   )r`   rl   )ra   r>   rm   r>   rB   rn   )r`   rl   rr   )ra   r>   rm   r>   rs   r>   rB   rb   )NNrE   rE   F)r;   r<   rX   rw   r=   rw   rx   r>   r?   r>   r@   rA   rB   rC   )rE   rE   F)r;   r<   r   r>   r   r>   rx   r>   r?   r>   r@   rA   rB   rC   )r   F)r;   r<   r   r>   r   r>   r   r>   r   r>   r?   r>   r@   rA   rB   rC   )r   r   rm   r>   rB   r   )r   )r   r   r   r   rB   rC   )rE   T)r   r   rm   r>   r   rA   rB   rC   )r   )r   r   rB   rC   )r   r   )r   rC   r   r>   r   r>   rB   r   )r   T)
r=   r>   r   r>   r   r>   r   r<   rB   r   )T)rf   rA   rB   r   )TF)r   r   r   r   rB   r   )r   r   rB   r   )r   r  r  r>   rB   r   )r   r   r   r   r  r>   r%   r>   r  r>   rB   r   )r   r`   Nr"  )
r;   r<   r=   r>   r#  rw   r$  r   rB   r   )r   r:   r   r"  )
r;   r<   r=   r>   r+  r   r$  r   rB   r   )r:  r;  rB   r   )rz   rA  r   )
r   r   rB  r<   rC  r   rD  r<   rB   r   )r   )r:  r;  rD  r<   rB   rH  )r:  r;  rD  r<   rB   r   )r   r`   r"  )r;   r<   r=   r>   r&  r   rB   r   )r   r`   r   r"  )
r;   r<   r=   r>   r+  r   r&  r   rB   r   )
r;   r<   r   r   rm   r>   rY  r   rB   r   )r   r^  r:   )r;   r<   r_  r<   r=   r>   rB   r   )
rw  r<   rx  r<   ry  r>   rz  r>   rB   r   )r  r   r  r   r  rA   rB   r  )r  r  r  r  rB   r  )r7  r   r.  r   rB   r   )r  r   r.  r   rB   r   )r  r;  r  r;  rB   r   )r  r;  r  r;  rB   r  )r  r   r7  r   r.  r   rB   r   )r   r   r  r   r  r  rB   r  )r   r   r  r   rB   r  )r   r   r  r   rB   r   )M
__future__r   typingr   r   r   r   r   rF   enumr	   
ezdxf.mathr
   r   r   r   r   r   r   r   r   r   r   r   ezdxf.render.meshr   r   __all__r   rG   r   r   r   r   r   r   r   r    r   r!   r"   r#   r$   r%   r&   r'   r   r   r   r(   r)   r  r  r*   r,   r-   r.   r0   r1   r/   r2   r3   r4   r5   r6   r  r   r  r7   r8   r  r  r9   r  r  r  r+   r   rQ   rP   <module>r     s   # " " " " " C C C C C C C C C C C C C C                                   @ ? ? ? ? ? ? ?# # #N HM) ) ) ) )B x%@ %@ %@ %@ %@R MN* * * * *,	J 	J 	J 	J 	J .3B B B B B7 7 7 7 7  ;?) ) ) ) )\ #"1 1 1 1 1p 3 3 3 3 3l    G    P P P P Pf !%Q

1 ' ' ' ' 'T      ?C9 9 9 9 9(1 1 1 1 1" GL	 	 	 	 	  ) ) ) ) )B 	DAqMMDAqMMDAqMMDAqMMDAqMMDAqMMDAqMMDAqMM	 	DtTDtTDtTDtTDtTDtTDtTDtT	 LLLLLLLLLLLL
    $ EJ#. #. #. #. #.L      & 
	
P. P. P. P. P. P.h "& 	! 
! ! ! ! ! !J ! 	% 
% % % % % %V 
	. . . . . .B 	N N N N N6 :;6 6 6 6 6<  
	     F .
 
. . . . . .: !	% 
% % % % % %V 8	" 
" " " " " "L 78G.BFG. G. G. G. G. G.V xG. 
G. G. G. G. G. G.TE E E E   	 	 	 	 5< D D D D D. 4; H H H H H) ) ) )   2 2 2 2,( ( ( (&   2     , 
	! ! ! ! ! ! ! !rQ   