
    mjzZ                       U d dl mZ d dlmZmZmZmZmZmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlZd dlZd dlmZmZ d dlmZmZmZmZmZmZmZmZmZ erd d	l m!Z! d d
l"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( g dZ) edd      Z* edd      Z+eeeeef   Z,de-d<   ee   Z.de-d<   ed   Z/de-d<    G d d      Z0 G d de0      Z1	 	 	 	 	 	 	 	 	 	 d dZ2 ed      Z3 G d de0      Z4d!dZ5 G d de      Z6y)"    )annotations)TYPE_CHECKINGIterableTupleUnioncastSequenceOptional)	TypeAlias)abstractmethod)
namedtupleNVTX_EXTRA_VERTEX_CREATEDVTX_SPLINE_FRAME_CONTROL_POINT)	Vec2Vec3UVecBSplineConstructionRayOCSParallelRaysErrorbulge_to_arcConstructionArc)Drawing)
DXFGraphicSolidTraceFace3d
LWPolylinePolyline)TraceBuilderLinearTraceCurvedTraceLinearStation)vertexstart_width	end_widthCurveStation)vertex0vertex1r   FacePolygon)r   r   r   Quadrilateralc                  8    e Zd Zedd       ZddZ	 d	 	 	 ddZy)	AbstractTracec                     y N selfs    ?/DATA/.local/lib/python3.12/site-packages/ezdxf/render/trace.pyfaceszAbstractTrace.faces2   s     	    c           	     
   dd}g }g }| j                         D ]-  \  }}}}|j                  ||f       |j                  ||f       / t         ||            }|j                  t        t         ||                         |S )Nc              3     K   t        |       sy t        |       }t        |      }| |D ]  }|j                  |      r| |} y wr1   )leniternextisclose)vertices	_verticesprevr%   s       r5   mergez$AbstractTrace.polygon.<locals>.merge;   sG     x=XI	?DJ#||F+ L!D $s   =A	 	A	)r>   r,   returnzIterable[UVec])r6   extendlistreversed)	r4   rA   forward_contourbackward_contourup1down1down2up2contours	            r5   polygonzAbstractTrace.polygon:   s    
	" ')')&*jjl"Cs""E5>2##S#J/ '3 u_-.xU+;%< =>?r7   Nc              #  <  K   ddl m} |dvrt        d| d      t        |xs i       }| j	                         D ]]  }t        d      D ]  }||   |d| <    |dk7  r|d	   |d
<   |d   |d<    ||||      }|r|j                  j                  |       | _ yw)a  
        Yields faces as SOLID, TRACE or 3DFACE entities with DXF attributes
        given in `dxfattribs`.

        If a document is given, the doc attribute of the new entities will be
        set and the new entities will be automatically added to the entity
        database of that document.

        Args:
            dxftype: DXF type as string, "SOLID", "TRACE" or "3DFACE"
            dxfattribs: DXF attributes for SOLID, TRACE or 3DFACE entities
            doc: associated document

        r   )new>   SOLIDTRACE3DFACEzInvalid dxftype .   vtxrR      vtx2   vtx3N)ezdxf.entities.factoryrO   	TypeErrordictr6   rangeentitydbadd)r4   dxftype
dxfattribsdocrO   faceientitys           r5   virtual_entitieszAbstractTrace.virtual_entitiesQ   s     " 	/66.wiq9::**+
JJLD1X(,Q
S9%  ("%)!W
6"%)!W
6"*c2F  (L !s   BBrB   zIterable[Face])rB   r,   rQ   NNrb   zOptional[Drawing]rB   zIterable[Quadrilateral])__name__
__module____qualname__r   r6   rM   rf   r2   r7   r5   r/   r/   1   s5     0 JN!5F!	 !r7   r/   c                  X    e Zd ZdZd	dZd Zd Zed
d       Z	 d	 	 	 	 	 	 	 ddZ	ddZ
y)r"   ztLinear 2D banded lines like polylines with start- and end width.

    Accepts 3D input, but z-axis is ignored.

    c                     g | _         d| _        y Ng-q=)	_stationsabs_tolr3   s    r5   __init__zLinearTrace.__init__|   s    .0r7   c                ,    t        | j                        S r1   r:   rp   r3   s    r5   __len__zLinearTrace.__len__       4>>""r7   c                     | j                   |   S r1   rp   r4   items     r5   __getitem__zLinearTrace.__getitem__       ~~d##r7   c                ,    t        | j                        S )z%`True` if at least one station exist.)boolrp   r3   s    r5   
is_startedzLinearTrace.is_started   s     DNN##r7   Nc           	         ||}t        |      }| j                  }t        |      r:|d   j                  j	                  || j
                        r|j                          |j                  t        |t        |      t        |                   y)aa  Add a trace station (like a vertex) at location `point`,
        `start_width` is the width of the next segment starting at this station,
        `end_width` is the end width of the next segment.

        Adding the last location again, replaces the actual last location e.g.
        adding lines (a, b), (b, c), creates only 3 stations (a, b, c), this is
        very important to connect to/from splines.

        Args:
            point: 2D location (vertex), z-axis of 3D vertices is ignored.
            start_width: start width of next segment
            end_width:  end width of next segment

        N)rq   )
r   rp   r~   r%   r=   rq   popappendr$   float)r4   pointr&   r'   stationss        r5   add_stationzLinearTrace.add_station   sp    " #IU>>>hrl1199%9VLLNeU;-?yAQRSr7   c           	   #     K   | j                    t               }|dk  ry	 	 	 	 d fd}	 	 	 	 	 	 	 	 d	d} d   j                  j                   d   j                        }g t	        |dz
        D ]:  } |   \  }}} |dz      j                  }	j                  t        ||	||             <  |d      \  }
}d}d}d   \  }}}}t	        t                    D ]  }|   \  }}}}|dk(  r;|r0 |t              dz
        \  }} |||
|      } ||||      }|}|}n|}|}|
}|}n |||
|      } ||||      }|t              dz
  k  r+ ||dz         \  }} ||||      } |||
|      }|
}|}|}
|}n|}|}||||f  yw)
a2  Yields all faces as 4-tuples of :class:`~ezdxf.math.Vec2` objects.

        First and last miter is 90 degrees if the path is not closed, otherwise
        the intersection of first and last segment is taken into account,
        a closed path has to have explicit the same last and first vertex.

        rX   Nc                J      fd}    \  }}}} |||       |||      fS )z0Create offset rays from segment offset vertices.c                    | j                  |      r8   j                  dz      j                  z
  j                  }t        | |      S t        | |      S )N   )r=   r%   angler   )v1v2r   segmentr   s      r5   rayz3LinearTrace.faces.<locals>.offset_rays.<locals>.ray   sX    ::b> !)008GaK3H3O3OOe  +2u55*2r22r7   r2   )r   r   left1left2right1right2segmentsr   s   `     r5   offset_raysz&LinearTrace.faces.<locals>.offset_rays   s6    
3 ,4G+<(E5&&ue$c&&&999r7   c                    t        | j                  j                  |j                              }|dk  st        t        j                  |z
        dk  r|S 	 | j                  |      S # t        $ r |cY S w xY w)z7Intersect two rays but take parallel rays into account.g*5{?)abs	directionangle_betweenmathpi	intersectr   )ray1ray2defaultr   s       r5   r   z$LinearTrace.faces.<locals>.intersect   sj    
 44T^^DEEx3tww#7(#B~~d++$ s   A' 'A54A5r   r   r   )r   intrB   z'tuple[ConstructionRay, ConstructionRay])r   r   r   r   r   r   rB   r   )rp   r:   r%   r=   r]   r   _normal_offset_points)!r4   countr   r   	is_closedstationstart_vertexr&   r'   
end_vertexoffset_ray1offset_ray2prev_offset_ray1prev_offset_ray2last_up1last_up2
last_down1
last_down2rd   rH   rK   rI   rJ   last_offset_ray1last_offset_ray2vtx0vtx1next_offset_ray1next_offset_ray2rW   rY   r   r   s!                                  @@r5   r6   zLinearTrace.faces   s5     >>H19	:	:4	:$	!	)8	CG		 QK&&..x|/B/BC	 UQY'G3;G3D0L+y!'A+.55J OO%lJYW ( $/q> [ 6>b\2(J
s8}%A%-a["CeUAv :ES]UVEV9W6$&6$%5{CHD$%5{EJD  $H!%J D D#. #.  !!1;D !1;F3x=1$$5@Q5G2 "2 !1;F !1;D#. #. .. "dD((M &s   FF
rB   None)rB   r~   r1   )r   r   r&   r   r'   zOptional[float]rB   r   rg   )rj   rk   rl   __doc__rr   ru   r{   propertyr   r   r6   r2   r7   r5   r"   r"   u   sa    #$ $ $
 MQTT(-T:IT	T6o)r7   r"   c                    || z
  j                         }|j                  d      }|j                  |dz        }|j                  |dz        }| |z   ||z   | |z
  ||z
  fS )NTrX   )	normalize
orthogonal)startendr&   r'   
dir_vectororthooffset_start
offset_ends           r5   r   r     st     +((*J!!$'E??;?3LQ/Jjj	 r7   )r   r   c                      e Zd ZdZd
dZd Zd Ze	 	 	 	 	 	 	 	 	 	 dd       Ze	 d	 	 	 	 	 	 	 	 	 dd       Z	ddZ
ddZy	)r#   z2D banded curves like arcs or splines with start- and end width.

    Represents always only one curved entity and all miter of curve segments
    are perpendicular to curve tangents.

    Accepts 3D input, but z-axis is ignored.

    c                    g | _         y r1   rx   r3   s    r5   rr   zCurvedTrace.__init__4  s	    -/r7   c                ,    t        | j                        S r1   rt   r3   s    r5   ru   zCurvedTrace.__len__7  rv   r7   c                     | j                   |   S r1   rx   ry   s     r5   r{   zCurvedTrace.__getitem__:  r|   r7   c                F    |        }|dz   }t        j                  d|j                  |      }t        |j	                  |d      t        j                  |||            D ]>  \  \  }}	}
t        |	      j                  d      }|j                  t        |      ||
       @ |S )z
        Create curved trace from a B-spline.

        Args:
            spline: :class:`~ezdxf.math.BSpline` object
            start_width: start width
            end_width: end width
            segments: count of segments for approximation

        r   r   )nT)nplinspacemax_tzipderivativesr   r   _append)clsspliner&   r'   r   curve_tracer   tr   
derivativewidthnormals               r5   from_splinezCurvedTrace.from_spline=  s    $ e1KK6<</*-qA&KE(R+
&UJ *%006FUVU;	+

 r7   c                   |j                   dk  rt        d|j                    d       |        }t        t        j                  |j
                  dz  |z        d      dz   }t        |j                        }t        |j                  |j                  |            t        j                  |||            D ]  \  }}	|j                  |||z
  |	        |S )a  
        Create curved trace from an arc.

        Args:
            arc: :class:`~ezdxf.math.ConstructionArc` object
            start_width: start width
            end_width: end width
            segments: count of segments for full circle (360 degree)
                approximation, partial arcs have proportional less segments,
                but at least 3

        Raises:
            ValueError: if arc.radius <= 0

        r   zInvalid radius: rS   g     v@rV   r   )radius
ValueErrormaxr   ceil
angle_spanr   centerr   r>   anglesr   r   r   )
r   arcr&   r'   r   r   r   r   r   r   s
             r5   from_arczCurvedTrace.from_arcY  s    . ::?/

|1=>>eDIIcnnu4x?@!DqHcjj!LLE*+KKY6
LE5 uv~u=	

 r7   c                    t         j                  |      rt         }n|j                  |dz        }| j                  j	                  t        ||z   ||z
               y)z
        Add a curve trace station (like a vertex) at location `point`.

        Args:
            point: 2D curve location (vertex), z-axis of 3D vertices is ignored.
            normal: curve normal
            width:  width of station

        rX   N)	_NULLVEC2r=   r   rp   r   r(   )r4   r   r   r   s       r5   r   zCurvedTrace._append|  sL     V$F%%eai0Fl56>56>JKr7   c              #     K   t        | j                        }|dk  ryd}d}| j                  D ]  \  }}||}|}||||f |}|} yw)zBYields all faces as 4-tuples of :class:`~ezdxf.math.Vec2` objects.rX   Nrt   )r4   r   r   r   rW   rY   s         r5   r6   zCurvedTrace.faces  se     DNN#19..JD$|dD((DD )s   AA
Nr   )
r   r   r&   r   r'   r   r   r   rB   r#   @   )
r   r   r&   r   r'   r   r   r   rB   r#   )r   r   r   r   r   r   rB   r   rg   )rj   rk   rl   r   rr   ru   r{   classmethodr   r   r   r6   r2   r7   r5   r#   r#   *  s    0#$   	
  
 6       	 
   
   DL r7   r#   c                ,    | t         z  ry| t        z  ryy)aa  Determine if a vertex should be included in rendering based on its flags.

    According to the DXF specification:
    - Flag 0: Straight-segment vertex (include)
    - Flag 1: Extra curve-fit vertex (exclude - auto-generated)
    - Flag 2: Curve-fit tangent vertex (include - carries tangent info)
    - Flag 8: Spline-vertex (fit-point) for 2D spline (include)
    - Flag 16: Spline-frame control point (exclude - internal calculation only)

    Args:
        vertex_flags: The vertex flags value (group code 70)

    Returns:
        True if the vertex should be included in rendering, False otherwise
    FTr   )vertex_flagss    r5   #should_include_vertex_for_renderingr     s#    " .. 44 r7   c                  x    e Zd ZdZddZd Zd ZddZddZddZ	ddZ
dd	Z	 d	 	 	 ddZd Zeddd       Zy
)r!   a  Sequence of 2D banded lines like polylines with start- and end width or
    curves with start- and end width.


    .. note::

        Accepts 3D input, but z-axis is ignored. The :class:`TraceBuilder` is a
        2D only object and uses only the :ref:`OCS` coordinates!

    c                     g | _         d| _        y ro   )_tracesrq   r3   s    r5   rr   zTraceBuilder.__init__  s    ,.r7   c                ,    t        | j                        S r1   )r:   r   r3   s    r5   ru   zTraceBuilder.__len__  s    4<<  r7   c                     | j                   |   S r1   )r   ry   s     r5   r{   zTraceBuilder.__getitem__  s    ||D!!r7   c                :    | j                   j                  |       y)zAppend a new trace.N)r   r   r4   traces     r5   r   zTraceBuilder.append  s    E"r7   c              #  b   K   | j                   D ]  }|j                         E d{     y7 w)zaYields all faces as 4-tuples of :class:`~ezdxf.math.Vec2` objects
        in :ref:`OCS`.
        N)r   r6   r   s     r5   r6   zTraceBuilder.faces  s(      \\E{{}$$ "$s   #/-/c              #     K   | j                         D ]'  }t        |j                  fd|D                     ) yw)zaYields all faces as 4-tuples of :class:`~ezdxf.math.Vec3` objects
        in :ref:`WCS`.
        c              3  `   K   | ]%  }t        |j                  |j                         ' y wr1   r   xy.0v	elevations     r5   	<genexpr>z)TraceBuilder.faces_wcs.<locals>.<genexpr>  s#     )RT$qssACC*CT   +.N)r6   tuplepoints_to_wcs)r4   ocsr   rc   s     ` r5   	faces_wcszTraceBuilder.faces_wcs  s5      JJLD)))RT)RRSS !s   <?c              #  R   K   | j                   D ]  }|j                           yw)z{Yields for each sub-trace a single polygon as sequence of
        :class:`~ezdxf.math.Vec2` objects in :ref:`OCS`.
        N)r   rM   r   s     r5   polygonszTraceBuilder.polygons  s"      \\E--/! "s   %'c              #     K   | j                   D ]5  }t        |j                  fd|j                         D                     7 yw)z{Yields for each sub-trace a single polygon as sequence of
        :class:`~ezdxf.math.Vec3` objects in :ref:`WCS`.
        c              3  `   K   | ]%  }t        |j                  |j                         ' y wr1   r   r   s     r5   r   z,TraceBuilder.polygons_wcs.<locals>.<genexpr>  s#     !U_$qssACC";_r   N)r   r   r   rM   )r4   r   r   r   s     ` r5   polygons_wcszTraceBuilder.polygons_wcs  s>      \\E!!!UU]]_!UU  "s   AA	Nc              #  h   K   | j                   D ]  }|j                  |||      E d{     y7 w)ar  Yields faces as SOLID, TRACE or 3DFACE entities with DXF attributes
        given in `dxfattribs`.

        If a document is given, the doc attribute of the new entities will be
        set and the new entities will be automatically added to the entity
        database of that document.

        .. note::

            The :class:`TraceBuilder` is a 2D only object and uses only the
            :ref:`OCS` coordinates!

        Args:
            dxftype: DXF type as string, "SOLID", "TRACE" or "3DFACE"
            dxfattribs: DXF attributes for SOLID, TRACE or 3DFACE entities
            doc: associated document

        N)r   rf   )r4   r`   ra   rb   r   s        r5   rf   zTraceBuilder.virtual_entities  s1     * \\E--gz3GGG "Gs   &202c                *   | j                   }t        |      dk  ryt        |d   t              ret        |d   t              rQt	        t        |j                  d            }t	        t        |d         }|D ]  \  }}}|j                  |||        yyy)zEClose multi traces by merging first and last trace, if linear traces.rX   Nr   r   )r   r:   
isinstancer"   r   r   r   )r4   tracesfirstlastr   r&   r'   s          r5   closezTraceBuilder.close  s    v;?fQi-*VBZ2Ufjjm4EVBZ0D16-{I  Y? 27 3V-r7   c           	        |j                         }|dk(  rpt        d|      }|j                  j                  }g }|j                  D ]/  \  }}}}	}
t        ||      }|r|}|}	|j                  |||	|
f       1 |j                  }ni|dk(  rUt        d|      }|j                  st        d      |j                  }|j                  j                  }|j                  j                  }|j                  D cg c])  }t        |j                  j                  dd            r|+ }}g }|D ]  }t        |j                  j                         }|j                  j#                  d      r|j                  j$                  }n|}|j                  j#                  d	      r|j                  j&                  }	n|}	|j                  j(                  }
|j                  |||	|
f        nt        d
|       |r1|d   d   j+                  |d   d         s|j                  |d           |        }d}d}d}d}t-               }|D ]  \  }}}	}
|dk7  rt/        |||      \  }}}}|dkD  rt1        ||t3        j4                  |      t3        j4                  |      d      }|j6                  j+                  |      r|}|}n|}|}|j                  t8        j;                  ||||             d}|
dk7  rC|j<                  r.|j?                  |||	       |j                  |       t-               }|
}|}|	}|}|j?                  |||	        |j<                  r|j                  |       |rtA        |      dkD  r|jC                          |S c c}w )a  
        Create a complete trace from a LWPOLYLINE or a 2D POLYLINE entity, the
        trace consist of multiple sub-traces if :term:`bulge` values are
        present. Uses only the :ref:`OCS` coordinates!

        Args:
            polyline: :class:`~ezdxf.entities.LWPolyline` or 2D
                :class:`~ezdxf.entities.Polyline`
            segments: count of segments for bulge approximation, given count is
                for a full circle, partial arcs have proportional less segments,
                but at least 3

        
LWPOLYLINEr   POLYLINEr    z2D POLYLINE requiredflagsr   r&   r'   zInvalid DXF type r   g        NT)is_counter_clockwiser   )"r`   r   dxfconst_widthlwpointsr   r   closedis_2d_polyliner[   r   default_start_widthdefault_end_widthr>   r   getlocationhasattrr&   r'   bulger=   r"   r   r   r   degreesstart_pointr#   r   r   r   r:   r  )r   polyliner   r`   r  pointsr   r   r&   r'   r  r  r  r  r  r%   filtered_verticesr   store_bulgestore_start_widthstore_end_widthstore_pointlinear_tracer   r   start_angle	end_angler   r   swews                                  r5   from_polylinezTraceBuilder.from_polyline  sn    ""$l"L(3H",,22KF7?7H7H31k9e1: #.K +IxiGH 8I __F
"J1H** 677''F"*,,"B"B ( > > &.%6%6!%666vzz~~gq7QR %6  !
 F+

 3 34::%%m4"(**"8"8K"5K::%%k2 &

 4 4I 1I

((xiGH , /y9::&)A,..vbz!}=MM&)$#'"}4:0E;	5c!9E:6Y A:)[1Y/-1C ..u5,.,.LL!5!5c2r8!LM!|** ,,UKKLL.#.=L#$/!"+#$$UKCC 5;D ""LL&c%j1n KKMS!s   5.Nr   )r   r/   rB   r   rg   )r   r   r   r   rB   zIterable[Sequence[Vec3]])rB   zIterable[Polygon]rh   ri   r   )r   r   r   r   rB   r!   )rj   rk   rl   r   rr   ru   r{   r   r6   r  r  r  rf   r  r   r,  r2   r7   r5   r!   r!     sk    	!"#%T" JNH5FH	 H0	@ m mr7   r!   )
r   r   r   r   r&   r   r'   r   rB   r+   )r   r   rB   r~   )7
__future__r   typingr   r   r   r   r   r	   r
   typing_extensionsr   abcr   collectionsr   r   numpyr   ezdxf.lldxf.constr   r   
ezdxf.mathr   r   r   r   r   r   r   r   r   ezdxf.documentr   ezdxf.entitiesr   r   r   r   r   r    __all__r$   r(   r+   __annotations__r,   r-   r/   r"   r   r   r#   r   r!   r2   r7   r5   <module>r9     s   #   (  "   V
 
 
 &UU
8?,RS .*@AdD$./i /d^ # !;<y <A AH`)- `)F).;@	 L	q- qh>I8 Ir7   