Ë
    £èh>  ã                  ó®   — d dl mZ d dlmZ d dlmZmZmZ d dlm	Z	m
Z
mZ dgZd ZdZdZdZd	Z G d
„ d«      Z G d„ d«      Z G d„ d«      Z G d„ d«      Zy)é    )Úannotations)ÚOptional)ÚVec3Úbest_fit_normalÚnormal_vector_3p)ÚMeshVertexMergerÚMeshBuilderÚMeshTransformerÚCSGé   é   é   gñhãˆµøä>c                  óf   — e Zd ZdZdZd
d„Zedd„«       Zdd„Zdd„Z	dd„Z
	 	 	 	 	 	 	 	 	 	 	 	 dd„Zy	)ÚPlanezRepresents a plane in 3D space.©ÚnormalÚwc                ó    — || _         || _        y ©Nr   )Úselfr   r   s      ú2lib/python3.12/site-packages/ezdxf/addons/pycsg.pyÚ__init__zPlane.__init__6   s   € ØˆŒàˆ�ó    c                óR   — t        |||«      }t        ||j                  |«      «      S r   )r   r   Údot)ÚclsÚaÚbÚcÚns        r   Úfrom_pointszPlane.from_points;   s%   € ä˜Q  1Ó%ˆÜ�Q˜Ÿ™˜a›Ó!Ð!r   c                óB   — t        | j                  | j                  «      S r   )r   r   r   ©r   s    r   ÚclonezPlane.clone@   s   € Ü�T—[‘[ $§&¡&Ó)Ð)r   c                óL   — | j                    | _         | j                   | _        y r   r   r#   s    r   Úflipz
Plane.flipC   s   € Ø—{‘{�lˆŒØ—&‘&�ˆ�r   c                ó<   — d| j                   › d| j                  › d�S )NzPlane(ú, Ú)r   r#   s    r   Ú__repr__zPlane.__repr__G   s   € Ø˜Ÿ™�} B t§v¡v h¨aÐ0Ð0r   c                óì  — d}g }|j                   }|j                  }	|D ]g  }
| j                  j                  |
«      | j                  z
  }|t
         k  rt        }n|t
        kD  rt        }nt        }||z  }|j                  |«       Œi |t        k(  rV| j                  j                  |j                  j                  «      dkD  r|j                  |«       y|j                  |«       y|t        k(  r|j                  |«       y|t        k(  r|j                  |«       y|t        k(  �rMg }g }t        |«      }t        |«      D ]Ú  }|dz   |z  }||   }||   }||   }
||   }|t        k7  r|j                  |
«       |t        k7  r|j                  |
«       ||z  t        k(  sŒ`| j                  | j                  j                  |
«      z
  | j                  j                  ||
z
  «      z  }|
j                  ||«      }|j                  |«       |j                  |«       ŒÜ t        |«      dk\  r|j                  t        ||	¬«      «       t        |«      dk\  r|j                  t        ||	¬«      «       yyy)ah  
        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)Úverticesr-   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_typesr.   r-   Ú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_polygonzPlane.split_polygonJ   sB  € ð ˆØˆØ×#Ñ#ˆØ—‘ˆó ˆFØ—{‘{—‘ vÓ.°·±Ñ7ˆHØœ=˜.Ò(Ü"‘ØœMÒ)Ü#‘ä&�Ø˜KÑ'ˆLØ×Ñ Õ,ð ð œ8Ò#Ø�{‰{�‰˜wŸ}™}×3Ñ3Ó4°qÒ8Ø×%Ñ% gÕ.à×$Ñ$ WÕ-ØœUÒ"Ø�L‰L˜Õ!ØœTÒ!Ø�K‰K˜Õ ØœXÓ%ØˆNØˆMÜ˜x›=ˆLÜ˜|Ö,�Ø# a™i¨<Ñ7�
Ø*¨5Ñ1�Ø#/°
Ñ#;Ð Ø! %™�Ø& zÑ2�Ø¤$Ò&Ø"×)Ñ)¨&Ô1Ø¤%Ò'Ø!×(Ñ(¨Ô0ØÐ"2Ñ2´xÓ?àŸ™ §¡§¡°Ó!8Ñ8ØŸ™Ÿ™¨°fÑ(<Ó=ñ,>Ð(ð 06¯{©{Ø#Ð%9ó0Ð,ð #×)Ñ)Ð*BÔCØ!×(Ñ(Ð)AÕBð% -ô& �>Ó" aÒ'Ø—‘œW ^¸FÔCÔDÜ�=Ó! QÒ&Ø—‘œG M¸&ÔAÕBð 'ð3 &r   N)r   r   r   Úfloat)r   r   r   r   r   r   Úreturnr   )rO   r   ©rO   ÚNone©rO   Ústr)r:   z	'Polygon'r;   úlist[Polygon]r<   rT   r=   rT   r>   rT   rO   rQ   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   Úclassmethodr!   r$   r&   r*   rM   © 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                  ó6   — e Zd ZdZdZdd	d„Zd
d„Zdd„Zdd„Zy)r9   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

    )r.   r4   r-   c                óÈ   — || _         	 t        |d   |d   |d   «      }t	        ||j                  |d   «      «      | _        || _        y # t        $ r t        |«      }Y ŒAw xY w)Nr   r   r   )r.   r   ÚZeroDivisionErrorr   r   r   r4   r-   )r   r.   r-   r   s       r   r   zPolygon.__init__    sg   € Ø ˆŒð	/Ü% h¨q¡k°8¸A±;ÀÈÁÓLˆFô ˜6 6§:¡:¨h°q©kÓ#:Ó;ˆŒ
àˆ�øô	 !ò 	/Ü$ XÓ.ŠFð	/ús   ‰A
 Á
A!Á A!c                óV   — t        t        | j                  «      | j                  ¬«      S )Nr,   )r9   Úlistr.   r-   r#   s    r   r$   zPolygon.cloneª   s   € Ü”t˜DŸM™MÓ*°4·;±;Ô?Ð?r   c                ól   — | j                   j                  «        | j                  j                  «        y r   )r.   Úreverser4   r&   r#   s    r   r&   zPolygon.flip­   s    € Ø�‰×ÑÔØ�
‰
�‰Õr   c                ól   — dj                  d„ | j                  D «       «      }d|› d| j                  › d�S )Nr(   c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr   )Úrepr)Ú.0Úvs     r   Ú	<genexpr>z#Polygon.__repr__.<locals>.<genexpr>²   s   è ø€ Ð5¡} !”d˜1—g¡}ùs   ‚z	Polygon([z], mesh=r)   )Újoinr.   r-   )r   rg   s     r   r*   zPolygon.__repr__±   s3   € Ø�I‰IÑ5 t§}¢}Ó5Ó5ˆØ˜1˜#˜X d§k¡k ]°!Ð4Ð4r   N©r   )r.   z
list[Vec3]r-   Úint)rO   r9   rP   rR   )	rU   rV   rW   rX   rY   r   r$   r&   r*   r[   r   r   r9   r9   ’   s#   „ ñ	ð 0€Iôó@óô5r   r9   c                  óN   — e Zd ZdZdZddd„Zdd„Zdd„Zdd„Zdd„Z	dd	„Z
dd
„Zy)ÚBSPNodea{  
    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.
    )r4   r=   r>   ÚpolygonsNc                ód   — d | _         d | _        d | _        g | _        |r| j	                  |«       y y r   )r4   r=   r>   rn   Úbuild©r   rn   s     r   r   zBSPNode.__init__Á   s2   € Ø&*ˆŒ
Ø(,ˆŒ
Ø'+ˆŒ	Ø')ˆŒÙØ�J‰J�xÕ ð r   c                ó€  — t        «       }| j                  r| j                  j                  «       |_        | j                  r| j                  j                  «       |_        | j                  r| j                  j                  «       |_        | j
                  D �cg c]  }|j                  «       ‘Œ c}|_        |S c c}w r   )rm   r4   r$   r=   r>   rn   )r   ÚnodeÚps      r   r$   zBSPNode.cloneÉ   s‚   € Ü‹yˆØ�:Š:ØŸ™×)Ñ)Ó+ˆDŒJØ�:Š:ØŸ™×)Ñ)Ó+ˆDŒJØ�9Š9ØŸ	™	Ÿ™Ó)ˆDŒIØ,0¯MªMÓ:©M q˜Ÿ™�¨MÑ:ˆŒØˆùò ;s   ÂB;c                ót  — | j                   D ]  }|j                  «        Œ | j                  €J ‚| j                  j                  «        | j                  r| j                  j	                  «        | j
                  r| j
                  j	                  «        | j
                  | j                  c| _        | _        y)zBConvert solid space to empty space and empty space to solid space.N)rn   r&   r4   r=   Úinvertr>   )r   Úpolys     r   rv   zBSPNode.invertÔ   s}   € à—M”MˆDØ�I‰I�Kð "à�z‰zÐ%Ð%Ð%Ø�
‰
�‰ÔØ�:Š:Ø�J‰J×ÑÔØ�9Š9Ø�I‰I×ÑÔØ $§	¡	¨4¯:©:ÐˆŒ
�D•Ir   c                ó@  — | j                   €|dd S g }g }|D ]!  }| j                   j                  |||||«       Œ# | j                  r| j                  j                  |«      }| j                  r| j                  j                  |«      }ng }|j                  |«       |S )z^Recursively remove all polygons in `polygons` that are inside this
        BSP tree.

        N)r4   rM   r=   Úclip_polygonsr>   Úextend)r   rn   r=   r>   r:   s        r   ry   zBSPNode.clip_polygonsà   s”   € ð
 �:‰:ÐØ™A�;Ðà!ˆØ ˆÛˆGØ�J‰J×$Ñ$ W¨e°T¸5À$ÕGð  ð �:Š:Ø—J‘J×,Ñ,¨UÓ3ˆEà�9Š9Ø—9‘9×*Ñ*¨4Ó0‰DàˆDà�‰�TÔØˆr   c                óâ   — |j                  | j                  «      | _        | j                  r| j                  j                  |«       | j                  r| j                  j                  |«       yy)z_Remove all polygons in this BSP tree that are inside the other BSP
        tree `bsp`.
        N)ry   rn   r=   Úclip_tor>   )r   Úbsps     r   r|   zBSPNode.clip_toø   sQ   € ð ×)Ñ)¨$¯-©-Ó8ˆŒØ�:Š:Ø�J‰J×Ñ˜sÔ#Ø�9Š9Ø�I‰I×Ñ˜cÕ"ð r   c                óø   — | j                   dd }| j                  r)|j                  | j                  j                  «       «       | j                  r)|j                  | j                  j                  «       «       |S )z/Return a list of all polygons in this BSP tree.N)rn   r=   rz   Úall_polygonsr>   rq   s     r   r   zBSPNode.all_polygons  sU   € à—=‘=¡Ð#ˆØ�:Š:Ø�O‰O˜DŸJ™J×3Ñ3Ó5Ô6Ø�9Š9Ø�O‰O˜DŸI™I×2Ñ2Ó4Ô5Øˆr   c                óN  — t        |«      dk(  ry| j                  €"|d   j                  j                  «       | _        | j                  j	                  |d   «       g }g }|dd D ]5  }| j                  j                  || j                  | j                  ||«       Œ7 t        |«      dkD  r6| j                  €t        «       | _        | j                  j                  |«       t        |«      dkD  r7| j                  €t        «       | _	        | j                  j                  |«       yy)a0  
        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   )
r6   r4   r$   rn   r3   rM   r=   rm   rp   r>   )r   rn   r=   r>   rw   s        r   rp   zBSPNode.build  sñ   € ô ˆx‹=˜AÒØØ�:‰:Ðà! !™×*Ñ*×0Ñ0Ó2ˆDŒJà�‰×Ñ˜X a™[Ô)Ø!ˆØ ˆà˜Q˜R“LˆDà�J‰J×$Ñ$Ø�d—m‘m T§]¡]°E¸4õð !ô ˆu‹:˜Š>Ø�z‰zÐ!Ü$›Y�”
Ø�J‰J×Ñ˜UÔ#Üˆt‹9�qŠ=Ø�y‰yÐ Ü#›I�”	Ø�I‰I�O‰O˜DÕ!ð r   r   )rn   zOptional[list[Polygon]])rO   rm   rP   )rn   rT   rO   rT   )r}   rm   rO   rQ   )rO   rT   )rn   rT   rO   rQ   )rU   rV   rW   rX   rY   r   r$   rv   ry   r|   r   rp   r[   r   r   rm   rm   ¶   s1   „ ñð 7€Iô!ó	ó
6óó0#óô"r   rm   c                  ój   — e Zd ZdZddd„Zedd„«       Zddd„Zdd„Zdd„Z	e	Z
dd„ZeZdd	„ZeZdd
„Zy)r   a1  
    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                ó¼   — |€g | _         y |j                  «       }|j                  «        |j                  «       D �cg c]  }t	        ||«      ‘Œ c}| _         y c c}w r   )rn   ÚcopyÚnormalize_facesÚfaces_as_verticesr9   )r   Úmeshr-   Ú	mesh_copyÚfaces        r   r   zCSG.__init__<  sV   € Øˆ<Ø+-ˆD�MàŸ	™	›ˆIØ×%Ñ%Ô'à2;×2MÑ2MÔ2OóÙ2O¨$”˜˜fÕ%Ð2OñˆD�Mùò s   ½Ac                ó(   — t        «       }||_        |S r   )r   rn   )r   rn   Úcsgs      r   Úfrom_polygonszCSG.from_polygonsF  s   € ä‹eˆØˆŒØˆ
r   c                ó¸   — t        «       }| j                  D ]-  }||j                  k(  sŒ|j                  |j                  «       Œ/ t        j                  |«      S )z“
        Returns a :class:`ezdxf.render.MeshTransformer` object.

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

        )r   rn   r-   Úadd_facer.   r
   Úfrom_builder)r   r-   r†   rˆ   s       r   r†   zCSG.meshL  sI   € ô  Ó!ˆØ—M”MˆDØ˜Ÿ™Ó$Ø—‘˜dŸm™mÕ,ð "ô ×+Ñ+¨DÓ1Ð1r   c                óz   — | j                  | j                  D �cg c]  }|j                  «       ‘Œ c}«      S c c}w r   )r‹   rn   r$   )r   rt   s     r   r$   z	CSG.cloneZ  s/   € Ø×!Ñ!°d·m²mÓ"D±m° 1§7¡7¥9°mÑ"DÓEÐEùÒ"Ds   š8c                ó¸  — t        | j                  «       j                  «      }t        |j                  «       j                  «      }|j                  |«       |j                  |«       |j	                  «        |j                  |«       |j	                  «        |j                  |j                  «       «       t        j                  |j                  «       «      S )a3  
        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   |            |       |
                 |       |            |       |
                 +-------+            +-------+
        )	rm   r$   rn   r|   rv   rp   r   r   r‹   ©r   Úotherr   r   s       r   Úunionz	CSG.union]  sŽ   € ô  �D—J‘J“L×)Ñ)Ó*ˆÜ�E—K‘K“M×*Ñ*Ó+ˆØ	�	‰	�!ŒØ	�	‰	�!ŒØ	�‰Œ
Ø	�	‰	�!ŒØ	�‰Œ
Ø	�‰�—‘Ó Ô!Ü× Ñ  §¡Ó!1Ó2Ð2r   c                óø  — t        | j                  «       j                  «      }t        |j                  «       j                  «      }|j                  «        |j	                  |«       |j	                  |«       |j                  «        |j	                  |«       |j                  «        |j                  |j                  «       «       |j                  «        t        j                  |j                  «       «      S )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   |
                 |       |
                 +-------+
        ©	rm   r$   rn   rv   r|   rp   r   r   r‹   r‘   s       r   ÚsubtractzCSG.subtracty  s    € ô  �D—J‘J“L×)Ñ)Ó*ˆÜ�E—K‘K“M×*Ñ*Ó+ˆØ	�‰Œ
Ø	�	‰	�!ŒØ	�	‰	�!ŒØ	�‰Œ
Ø	�	‰	�!ŒØ	�‰Œ
Ø	�‰�—‘Ó Ô!Ø	�‰Œ
Ü× Ñ  §¡Ó!1Ó2Ð2r   c                óØ  — t        | j                  «       j                  «      }t        |j                  «       j                  «      }|j                  «        |j	                  |«       |j                  «        |j	                  |«       |j	                  |«       |j                  |j                  «       «       |j                  «        t        j                  |j                  «       «      S )a¡  
        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   Ú	intersectzCSG.intersect—  s—   € ô  �D—J‘J“L×)Ñ)Ó*ˆÜ�E—K‘K“M×*Ñ*Ó+ˆØ	�‰Œ
Ø	�	‰	�!ŒØ	�‰Œ
Ø	�	‰	�!ŒØ	�	‰	�!ŒØ	�‰�—‘Ó Ô!Ø	�‰Œ
Ü× Ñ  §¡Ó!1Ó2Ð2r   c                óh   — | j                  «       }|j                  D ]  }|j                  «        Œ |S )zq
        Return a new CSG solid with solid and empty space switched. This solid is
        not modified.
        )r$   rn   r&   )r   rŠ   rt   s      r   ÚinversezCSG.inverse´  s+   € ð
 �j‰j‹lˆØ—”ˆAØ�F‰F�Hð àˆ
r   )Nr   )r†   zOptional[MeshBuilder]r-   rk   )rn   rT   rO   r   rj   )r-   rk   rO   r
   )rO   r   )r’   r   rO   r   )rU   rV   rW   rX   r   rZ   r‹   r†   r$   r“   Ú__add__r–   Ú__sub__r˜   Ú__mul__rš   r[   r   r   r   r   ,  sT   „ ñôð òó ðô
2óFó3ð4 €Gó3ð8 €Gó3ð6 €Gôr   N)Ú
__future__r   Útypingr   Ú
ezdxf.mathr   r   r   Úezdxf.renderr   r	   r
   Ú__all__r2   r1   r0   r5   r/   r   r9   rm   r   r[   r   r   Ú<module>r£      sn   ðõ #Ý ß >Ñ >ß GÑ Gð> ˆ'€à€Ø	€Ø€Ø€Ø€÷^Cñ ^C÷B!5ñ !5÷Hs"ñ s"÷lPò Pr   