
    hJ<                        S SK Jr  S SKJr  S SKJrJrJr  S SKJ	r	J
r
Jr  S/rS rSrSrSrS	r " S
 S5      r " S S5      r " S S5      r " S S5      rg)    )annotations)Optional)Vec3best_fit_normalnormal_vector_3p)MeshVertexMergerMeshBuilderMeshTransformerCSG         gh㈵>c                  z    \ rS rSrSrSrSS jr\SS j5       rSS jr	SS jr
SS jr            SS	 jrSrg
)Plane1   zRepresents a plane in 3D space.normalwc                    Xl         X l        g Nr   )selfr   r   s      D/var/www/html/env/lib/python3.13/site-packages/ezdxf/addons/pycsg.py__init__Plane.__init__6   s        c                N    [        XU5      n[        XDR                  U5      5      $ r   )r   r   dot)clsabcns        r   from_pointsPlane.from_points;   s!    Q1%Qa!!r   c                B    [        U R                  U R                  5      $ r   )r   r   r   r   s    r   clonePlane.clone@   s    T[[$&&))r   c                L    U R                   * U l         U R                  * U l        g r   r   r&   s    r   flip
Plane.flipC   s    {{l&&r   c                <    SU R                    SU R                   S3$ )NzPlane(, )r   r&   s    r   __repr__Plane.__repr__G   s    }Btvvha00r   c                   Sn/ nUR                   nUR                  n	U Hi  n
U R                  R                  U
5      U R                  -
  nU[
        * :  a  [        nOU[
        :  a  [        nO[        nXl-  nUR                  U5        Mk     U[        :X  aW  U R                  R                  UR                  R                  5      S:  a  UR                  U5        gUR                  U5        gU[        :X  a  UR                  U5        gU[        :X  a  UR                  U5        gU[        :X  GaM  / n/ n[        U5      n[        U5       H  nUS-   U-  nUU   nUU   nUU   n
UU   nU[        :w  a  UR                  U
5        U[        :w  a  UR                  U
5        UU-  [        :X  d  Md  U R                  U R                  R                  U
5      -
  U R                  R                  UU
-
  5      -  nU
R                  UU5      nUR                  U5        UR                  U5        M     [        U5      S:  a  UR                  [        XS95        [        U5      S:  a  UR                  [        XS95        ggg)a8  
Split `polygon` by this plane if needed, then put the polygon or polygon
fragments in the appropriate lists. Coplanar polygons go into either
`coplanarFront` or `coplanarBack` depending on their orientation with
respect to this plane. Polygons in front or in back of this plane go into
either `front` or `back`
r   r   r   meshidN)verticesr3   r   r   r   PLANE_EPSILONBACKFRONTCOPLANARappendplaneSPANNINGlenrangelerpPolygon)r   polygoncoplanar_frontcoplanar_backfrontbackpolygon_typevertex_typesr4   r3   vertexdistancevertex_typefront_verticesback_verticeslen_verticesindex
next_indexnext_vertex_typenext_vertexinterpolation_weightplane_intersection_points                         r   split_polygonPlane.split_polygonJ   s<    ## F{{v.7H=.("M)#&'L,  8#{{w}}334q8%%g.$$W-U"LL!T!KK X%NMx=L|,#ai<7
*51#/
#; !%&z2$&"))&1%'!((0"22x?!88f(<=,>( 06{{#%90, #))*BC!(()AB% -& >"a'W^CD=!Q&GMAB '3 &r   N)r   r   r   float)r   r   r    r   r!   r   returnr   )rV   r   rV   NonerV   str)r@   z	'Polygon'rA   list[Polygon]rB   r[   rC   r[   rD   r[   rV   rX   )__name__
__module____qualname____firstlineno____doc__	__slots__r   classmethodr#   r'   r*   r/   rS   __static_attributes__ r   r   r   r   1   s    )I
 " "*1ECEC &EC %	EC
 EC EC 
ECr   r   c                  H    \ rS rSrSrSrS
SS jjrSS jrSS jrSS jr	Sr
g	)r?      a  
Represents a convex polygon. The vertices used to initialize a polygon must
be coplanar and form a convex loop, the `meshid` argument associates a polygon
to a mesh.

Args:
    vertices: polygon vertices as :class:`Vec3` objects
    meshid: id associated mesh

)r4   r:   r3   c                    Xl          [        US   US   US   5      n[	        X3R                  US   5      5      U l        X l        g ! [         a    [        U5      n N@f = f)Nr   r   r   )r4   r   ZeroDivisionErrorr   r   r   r:   r3   )r   r4   r3   r   s       r   r   Polygon.__init__   sa     	/%hqk8A;LF 6::hqk#:;
	 ! 	/$X.F	/s   A AAc                P    [        [        U R                  5      U R                  S9$ )Nr2   )r?   listr4   r3   r&   s    r   r'   Polygon.clone   s    tDMM*4;;??r   c                l    U R                   R                  5         U R                  R                  5         g r   )r4   reverser:   r*   r&   s    r   r*   Polygon.flip   s     

r   c                l    SR                  S U R                   5       5      nSU SU R                   S3$ )Nr-   c              3  8   #    U  H  n[        U5      v   M     g 7fr   )repr).0vs     r   	<genexpr>#Polygon.__repr__.<locals>.<genexpr>   s     5}!d1gg}s   z	Polygon([z], mesh=r.   )joinr4   r3   )r   rt   s     r   r/   Polygon.__repr__   s3    II5t}}551#Xdkk]!44r   )r3   r:   r4   Nr   )r4   z
list[Vec3]r3   int)rV   r?   rW   rY   )r\   r]   r^   r_   r`   ra   r   r'   r*   r/   rc   rd   r   r   r?   r?      s#    	 0I@5r   r?   c                  f    \ rS rSrSrSrSSS jjrSS jrSS jrSS jr	SS	 jr
SS
 jrSS jrSrg)BSPNode   ac  
Holds a node in a BSP tree. A BSP tree is built from a collection of polygons
by picking a polygon to split along. That polygon (and all other coplanar
polygons) are added directly to that node and the other polygons are added to
the front and/or back subtrees. This is not a leafy BSP tree since there is
no distinction between internal and leaf nodes.
)r:   rC   rD   polygonsNc                n    S U l         S U l        S U l        / U l        U(       a  U R	                  U5        g g r   )r:   rC   rD   r~   buildr   r~   s     r   r   BSPNode.__init__   s2    &*
(,
'+	')JJx  r   c                   [        5       nU R                  (       a  U R                  R                  5       Ul        U R                  (       a  U R                  R                  5       Ul        U R                  (       a  U R                  R                  5       Ul        U R
                   Vs/ s H  o"R                  5       PM     snUl        U$ s  snf r   )r|   r:   r'   rC   rD   r~   )r   nodeps      r   r'   BSPNode.clone   s    y::))+DJ::))+DJ99		)DI,0MM:MqM: ;s   )Cc                   U R                    H  nUR                  5         M     U R                  c   eU R                  R                  5         U R                  (       a  U R                  R	                  5         U R
                  (       a  U R
                  R	                  5         U R
                  U R                  sU l        U l        g)zBConvert solid space to empty space and empty space to solid space.N)r~   r*   r:   rC   invertrD   )r   polys     r   r   BSPNode.invert   s}    MMDIIK "zz%%%

::JJ99II $		4::
DIr   c                V   U R                   c  USS $ / n/ nU H   nU R                   R                  XBX2U5        M"     U R                  (       a  U R                  R                  U5      nU R                  (       a  U R                  R                  U5      nO/ nUR                  U5        U$ )zNRecursively remove all polygons in `polygons` that are inside this
BSP tree.

N)r:   rS   rC   clip_polygonsrD   extend)r   r~   rC   rD   r@   s        r   r   BSPNode.clip_polygons   s    
 ::A;! GJJ$$WT$G   ::JJ,,U3E9999**40DDTr   c                    UR                  U R                  5      U l        U R                  (       a  U R                  R                  U5        U R                  (       a  U R                  R                  U5        gg)zORemove all polygons in this BSP tree that are inside the other BSP
tree `bsp`.
N)r   r~   rC   clip_torD   )r   bsps     r   r   BSPNode.clip_to   sQ     ))$--8::JJs#99IIc" r   c                   U R                   SS nU R                  (       a)  UR                  U R                  R                  5       5        U R                  (       a)  UR                  U R                  R                  5       5        U$ )z/Return a list of all polygons in this BSP tree.N)r~   rC   r   all_polygonsrD   r   s     r   r   BSPNode.all_polygons  sU    ==#::OODJJ335699OODII2245r   c                Z   [        U5      S:X  a  gU R                  c"  US   R                  R                  5       U l        U R                  R	                  US   5        / n/ nUSS  H4  nU R                  R                  X@R                  U R                  X#5        M6     [        U5      S:  a7  U R                  c  [        5       U l        U R                  R                  U5        [        U5      S:  a8  U R                  c  [        5       U l	        U R                  R                  U5        gg)a  
Build a BSP tree out of `polygons`. When called on an existing tree, the
new polygons are filtered down to the bottom of the tree and become new
nodes there. Each set of polygons is partitioned using the first polygon
(no heuristic is used to pick a good split).
r   Nr   )
r<   r:   r'   r~   r9   rS   rC   r|   r   rD   )r   r~   rC   rD   r   s        r   r   BSPNode.build  s     x=A::!!**002DJXa[)! QRLDJJ$$mmT]]E ! u:>zz!$Y
JJU#t9q=yy #I	IIOOD! r   )rD   rC   r:   r~   r   )r~   zOptional[list[Polygon]])rV   r|   rW   )r~   r[   rV   r[   )r   r|   rV   rX   )rV   r[   )r~   r[   rV   rX   )r\   r]   r^   r_   r`   ra   r   r'   r   r   r   r   r   rc   rd   r   r   r|   r|      s1     7I!	
60#"r   r|   c                      \ rS rSrSrSSS jjr\SS j5       rSSS jjrSS jr	SS jr
\
rSS	 jr\rSS
 jr\rSS jrSrg)r   i,  a	  
Constructive Solid Geometry (CSG) is a modeling technique that uses Boolean
operations like union and intersection to combine 3D solids. This class
implements CSG operations on meshes.

New 3D solids are created from :class:`~ezdxf.render.MeshBuilder` objects
and results can be exported as :class:`~ezdxf.render.MeshTransformer` objects
to `ezdxf` by method :meth:`mesh`.

Args:
    mesh: :class:`ezdxf.render.MeshBuilder` or inherited object
    meshid: individual mesh ID to separate result meshes, ``0`` is default

Nc                    Uc  / U l         g UR                  5       nUR                  5         UR                  5        Vs/ s H  n[	        XB5      PM     snU l         g s  snf r   )r~   copynormalize_facesfaces_as_verticesr?   )r   meshr3   	mesh_copyfaces        r   r   CSG.__init__<  sT    <+-DM		I%%'2;2M2M2O2O$%2ODM s   Ac                &    [        5       nXl        U$ r   )r   r~   )r   r~   csgs      r   from_polygonsCSG.from_polygonsF  s    e
r   c                    [        5       nU R                   H/  nXR                  :X  d  M  UR                  UR                  5        M1     [
        R                  " U5      $ )zs
Returns a :class:`ezdxf.render.MeshTransformer` object.

Args:
     meshid: individual mesh ID, ``0`` is default

)r   r~   r3   add_facer4   r
   from_builder)r   r3   r   r   s       r   r   CSG.meshL  sG      !MMD$dmm, " ++D11r   c                ~    U R                  U R                   Vs/ s H  oR                  5       PM     sn5      $ s  snf r   )r   r~   r'   )r   r   s     r   r'   	CSG.cloneZ  s-    !!dmm"Dm779m"DEE"Ds   :c                   [        U R                  5       R                  5      n[        UR                  5       R                  5      nUR                  U5        UR                  U5        UR	                  5         UR                  U5        UR	                  5         UR                  UR                  5       5        [        R                  UR                  5       5      $ )a  
Return a new CSG solid representing space in either this solid or in the
solid `other`. Neither this solid nor the solid `other` are modified::

    A.union(B)

    +-------+            +-------+
    |       |            |       |
    |   A   |            |       |
    |    +--+----+   =   |       +----+
    +----+--+    |       +----+       |
         |   B   |            |       |
         |       |            |       |
         +-------+            +-------+
)	r|   r'   r~   r   r   r   r   r   r   r   otherr   r    s       r   union	CSG.union]  s      DJJL))*EKKM**+			!			!	
			!	
	 !  !122r   c                   [        U R                  5       R                  5      n[        UR                  5       R                  5      nUR                  5         UR	                  U5        UR	                  U5        UR                  5         UR	                  U5        UR                  5         UR                  UR                  5       5        UR                  5         [        R                  UR                  5       5      $ )a  
Return a new CSG solid representing space in this solid but not in the
solid `other`. Neither this solid nor the solid `other` are modified::

    A.subtract(B)

    +-------+            +-------+
    |       |            |       |
    |   A   |            |       |
    |    +--+----+   =   |    +--+
    +----+--+    |       +----+
         |   B   |
         |       |
         +-------+
	r|   r'   r~   r   r   r   r   r   r   r   s       r   subtractCSG.subtracty  s      DJJL))*EKKM**+	
			!			!	
			!	
	 !	
  !122r   c                   [        U R                  5       R                  5      n[        UR                  5       R                  5      nUR                  5         UR	                  U5        UR                  5         UR	                  U5        UR	                  U5        UR                  UR                  5       5        UR                  5         [        R                  UR                  5       5      $ )aA  
Return a new CSG solid representing space both this solid and in the
solid `other`. Neither this solid nor the solid `other` are modified::

    A.intersect(B)

    +-------+
    |       |
    |   A   |
    |    +--+----+   =   +--+
    +----+--+    |       +--+
         |   B   |
         |       |
         +-------+
r   r   s       r   	intersectCSG.intersect  s      DJJL))*EKKM**+	
			!	
			!			!	 !	
  !122r   c                l    U R                  5       nUR                   H  nUR                  5         M     U$ )zY
Return a new CSG solid with solid and empty space switched. This solid is
not modified.
)r'   r~   r*   )r   r   r   s      r   inverseCSG.inverse  s+    
 jjlAFFH 
r   )r~   )Nr   )r   zOptional[MeshBuilder]r3   rz   )r~   r[   rV   r   ry   )r3   rz   rV   r
   )rV   r   )r   r   rV   r   )r\   r]   r^   r_   r`   r   rb   r   r   r'   r   __add__r   __sub__r   __mul__r   rc   rd   r   r   r   r   ,  sT      
2F34 G38 G36 Gr   N)
__future__r   typingr   
ezdxf.mathr   r   r   ezdxf.renderr   r	   r
   __all__r8   r7   r6   r;   r5   r   r?   r|   r   rd   r   r   <module>r      sn    #  > > G G> '	^C ^CB!5 !5Hs" s"lP Pr   