
    ^jc                       d Z ddlmZ ddlZddlZddlmZmZmZ ddl	m
Z
 ddlmZmZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZ 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)m*Z* ddlm+Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5m6Z6m7Z7m8Z8 ddl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZA ddlBmCZCmDZD ddlEmFZFmGZGmHZH ddlImJZJmKZKmLZLmMZMmNZNmOZOmPZP ddlQmRZRmSZS ddlTmUZUmVZV ddlWmXZXmYZYmZZZ ddl[m\Z\  G d deRe/         Z] G d de]      Z^ G d  d!e]      Z_ G d" d#e]      Z` eJj                  de]        eJj                  de^        eJj                  d$e_        eJj                  d%e`       y)&a  
build123d topology

name: composite.py
by:   Gumyr
date: January 07, 2025

desc:

This module defines advanced composite geometric entities for the build123d CAD system. It
introduces the `Compound` class as a central concept for managing groups of shapes, alongside
specialized subclasses such as `Curve`, `Sketch`, and `Part` for 1D, 2D, and 3D objects,
respectively. These classes streamline the construction and manipulation of complex geometric
assemblies.

Key Features:
- **Compound Class**:
  - Represents a collection of geometric shapes (e.g., vertices, edges, faces, solids) grouped
    hierarchically.
  - Supports operations like adding, removing, and combining shapes, as well as querying volumes,
    centers, and intersections.
  - Provides utility methods for unwrapping nested compounds and generating 3D text or coordinate
    system triads.

- **Specialized Subclasses**:
  - `Curve`: Handles 1D objects like edges and wires.
  - `Sketch`: Focused on 2D objects, such as faces.
  - `Part`: Manages 3D solids and assemblies.

- **Advanced Features**:
  - Includes Boolean operations, hierarchy traversal, and bounding box-based intersection detection.
  - Supports transformations, child-parent relationships, and dynamic updates.

This module leverages OpenCascade for robust geometric operations while offering a Pythonic
interface for efficient and extensible CAD modeling workflows.

license:

    Copyright 2025 Gumyr

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    )annotationsN)IterableIteratorSequence)combinations)PathLikefspath)overload)Self)BRepAlgoAPI_CommonBRepAlgoAPI_FuseBRepAlgoAPI_Section)gp_Ax3)Graphic3d_HTA_LEFTGraphic3d_HTA_CENTERGraphic3d_HTA_RIGHTGraphic3d_VTA_BOTTOMGraphic3d_VTA_CENTERGraphic3d_VTA_TOPGraphic3d_VTA_TOPFIRSTLINE)GProp_GProps)NCollection_Utf8String)StdPrs_BRepTextBuilderStdPrs_BRepFont)TopAbs_ShapeEnum)TopoDSTopoDS_BuilderTopoDS_CompoundTopoDS_IteratorTopoDS_Shape)PreOrderIter)AlignCenterOf	FontStyle	TextAlign)	TOLERANCEAxisColorLocationPlaneVector
VectorLikelogger)FONT_ASPECTFontManager   )EdgeWireMixin1D)Shape	ShapeListJointdowncast	shapetype
topods_dim!_make_topods_compound_from_shapes)Mixin3DSolid)FaceShell)_extrude_topods_shapetuplifyunwrapped_shapetype)Vertexc            	      `    e Zd ZdZdZ	 	 	 	 	 	 	 d$	 	 	 	 	 	 	 	 	 	 	 	 	 d% fdZed&d       Zed'd       Ze		 	 	 	 d(d       Z
e	d)d       Ze	d	dej                  ej                  ej                  fdd
dd
f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d*d       Ze	d+d       Zd,dZd-dZd.dZd/dZd0dZd Zd1dZej4                  fd2dZd3dZd4dZ	 d5	 	 	 	 	 d6dZ	 	 	 	 d7dZ	 	 d8	 	 	 	 	 	 	 d9dZ 	 d:	 	 	 	 	 d;dZ!	 	 	 d<	 	 	 	 	 	 	 	 	 d=dZ"d>d?dZ#d@dZ$dAdZ%d@dZ&d  Z'd@d!Z(d" Z)dBd#Z* xZ+S )CCompoundal  A Compound in build123d is a topological entity representing a collection of
    geometric shapes grouped together within a single structure. It serves as a
    container for organizing diverse shapes like edges, faces, or solids. This
    hierarchical arrangement facilitates the construction of complex models by
    combining simpler shapes. Compound plays a pivotal role in managing the
    composition and structure of intricate 3D models in computer-aided design
    (CAD) applications, allowing engineers and designers to work with assemblies
    of shapes as unified entities for efficient modeling and analysis.g      @Nc                    t        |t              r$t        |D cg c]  }|j                   c}      }	n|}	t        
|   |	|||       |dn|| _        |i n|| _        |g | _        y|| _        yc c}w )a7  Build a Compound from Shapes

        Args:
            obj (TopoDS_Compound | Iterable[Shape], optional): OCCT Compound or shapes
            label (str, optional): Defaults to ''.
            color (Color, optional): Defaults to None.
            material (str, optional): tag for external tools. Defaults to ''.
            joints (dict[str, Joint], optional): names joints. Defaults to None.
            parent (Compound, optional): assembly parent. Defaults to None.
            children (Sequence[Shape], optional): assembly children. Defaults to None.
        )objlabelcolorparentN )	
isinstancer   r:   wrappedsuper__init__materialjointschildren)selfrF   rG   rH   rO   rP   rI   rQ   stopods_compound	__class__s             U/opt/ringagent/.cad-venv/lib/python3.12/site-packages/build123d/topology/composite.pyrN   zCompound.__init__   s    , c8$?$'(q(O "O	 	 	
 '.H"Nb&.H )s   A3c                ,    t        | j                        S )zFThe dimension of the shapes within the Compound - None if inconsistent)r9   rL   rR   s    rV   _dimzCompound._dim   s     $,,''    c                z    t        d g | j                  t              | j                  t              D              S )z$volume - the volume of this Compoundc              3  4   K   | ]  }|j                     y wNvolume).0is     rV   	<genexpr>z"Compound.volume.<locals>.<genexpr>   s     T188T   )sumget_typer<   r>   rX   s    rV   r_   zCompound.volume   s2     T%St}}U';%SdmmE>R%STTTrZ   c                   t         j                  t        t         j                  t        t         j
                  t        t         j                  t        t         j                  t        t         j                  t        t         j                  t        t         j                  t        i}t!        |      } ||   t#        |            S )z6Returns the right type of wrapper, given a OCCT object)taTopAbs_VERTEXrB   TopAbs_EDGEr1   TopAbs_WIREr2   TopAbs_FACEr=   TopAbs_SHELLr>   TopAbs_SOLIDr<   TopAbs_COMPOUNDrD   TopAbs_COMPSOLIDr8   r7   )clsrF   constructor_lut
shape_types       rV   castzCompound.cast   sz     fNNDNNDNNDOOUOOU	
 s^
*z*8C=99rZ   c                f    t        t        j                   t        |j                  |                  S )a3  extrude

        Extrude a Shell into a Compound.

        Args:
            direction (VectorLike): direction and magnitude of extrusion

        Raises:
            ValueError: Unsupported class
            RuntimeError: Generated invalid result

        Returns:
            Edge: extruded shape
        )rD   r   r?   rL   )rp   rF   	directions      rV   extrudezCompound.extrude   s$      (=ckk9(UVWWrZ   Arial        c                   dd}|t        |      nd}t               }|rB|j                  |      r1|j                  |dd      }||v r|n|d   }|j	                  ||      }n|j	                  ||      }|d   t
        j                  t
        j                  t
        j                  fvrt        d|d          |d   t
        j                  t
        j                  t
        j                  t
        j                  fvrt        d|d          t
        j                  t        t
        j                  t        t
        j                  t        i|d      }t
        j                  t         t
        j                  t"        t
        j                  t$        t
        j                  t&        i|d      }t)        j*                  d	|j-                         j/                         |j1                  t2        |         j/                                t5               }t7        t9        |j-                         j/                               t2        |   t;        |            }|j=                         r|j?                  d       tA        tC        j@                  |jE                  |t9        |      tG               ||                  }tI        |d
      }|jK                  tM        |jO                         jQ                  |             }|	r1|jS                         }tA        |D cg c]  } |||	|       c}      }dd}|j=                         r|
dkD  r|jU                         D cg c]  }|jW                  |
d
z         }}|D cg c]  } ||jU                                }}tA        g       |z   }tY        |jS                         D cg c]  }|jZ                    c}      rt        d|
 d      |S c c}w c c}w c c}w c c}w )av  Text that optionally follows a path.

        The text that is created can be combined as with other sketch features by specifying
        a mode or rotated by the given angle. In addition, edges have been previously created
        with arc or segment, the text will follow the path defined by these edges. The start
        parameter can be used to shift the text along the path to achieve precise positioning.

        Args:
            txt (str): text to render
            font_size (float): size of the font in model units
            font (str, optional): font name. Defaults to "Arial"
            font_path (PathLike | str, optional): system path to font file. Defaults to None
            font_style (Font_Style, optional): font style, REGULAR, BOLD, BOLDITALIC, or
                ITALIC. Defaults to Font_Style.REGULAR
            text_align (tuple[TextAlign, TextAlign], optional): horizontal text align
                LEFT, CENTER, or RIGHT. Vertical text align BOTTOM, CENTER, TOP, or
                TOPFIRSTLINE. Defaults to (TextAlign.CENTER, TextAlign.CENTER)
            align (Align | tuple[Align, Align], optional): align MIN, CENTER, or MAX of
                object. Defaults to None
            position_on_path (float, optional): the relative location on path to position
                the text, values must be between 0.0 and 1.0. Defaults to 0.0
            text_path: (Edge | Wire, optional): path for text to follow. Defaults to None
                Compound object containing multiple Shapes representing the text
            single_line_width (float): width of outlined single line font.
                Defaults to 0.0

        Examples::

            fox = Compound.make_text(
                txt="The quick brown fox jumped over the lazy dog",
                font_size=10,
                position_on_path=0.1,
                text_path=jump_edge,
            )

        c                   | j                         }t        |j                  j                  |j                  j                  z   dz  dd      }||j                  |j
                  z  z   }|j                  |      }t        ddd      j                  |      }|j                  |      }| j                  ||z
        j                  t        |d      |       S )zReposition a glyph shape on provided path

            Local coordinates are used to calculate the position of the shape
            relative to the path. Global coordinates to position the shape.
               r   r0   r   r   r0   )bounding_boxr+   minXmaxlength
tangent_atget_signed_angleposition_at	translaterotater'   )	glyphpathpositionbboxface_bottom_centerrelative_position_on_wirewire_tangent
wire_anglewire_positions	            rV   position_glyphz*Compound.make_text.<locals>.position_glyph  s     %%'D!'dhhjj)@A(Eq!!L(03E3G3G$++3U(U%??+DEL1a99,GJ ,,-FGM??=3E#EFMM]I. rZ   NTFr   z9Horizontal TextAlign must be LEFT, CENTER, or RIGHT. Got r0   zEVertical TextAlign must be BOTTOM, CENTER, TOP, or TOPFIRSTLINE. Got z(Creating text with font %s located at %sr{   c                    t        t        j                  |       d         }|j                         j                  dk  r| }|S )Nr   )r=   r2   combine	normal_atZ)edgesfaces     rV   
_make_facez&Compound.make_text.<locals>._make_face  s;    U+A./D~~!!A%uKrZ   zsingle_line_width (zK) is too large for the text and produces invalid faces. Try a smaller width)r   r4   r   zEdge | Wirer   floatreturnr4   )r   zIterable[Edge]r   r=   ).r	   r/   
check_fontregister_font	find_fontr%   LEFTCENTERRIGHT
ValueErrorBOTTOMTOPTOPFIRSTLINEr   r   r   r   r   r   r   r-   infoFontName	ToCStringFontPathr.   Font_BRepTextBuilderr   r   r   IsSingleStrokeFontSetCompositeCurveModerD   r   Performr   r@   r   r+   r}   to_align_offsetget_top_level_shapesr   	offset_2danyis_valid)rp   txt	font_sizefont	font_path
font_style
text_alignalignposition_on_path	text_pathsingle_line_widthr   font_path_strmanager
face_names	font_namesystem_fonthoriz_align
vert_alignbuilder	brep_font	text_flat
align_textglyphsgr   eoutlineofs                                 rV   	make_textzCompound.make_text   s   h	& .7-By)-W//> ..}dEJJ $
 2
1I!++IzBK!++D*=K a=1A1A9?? SS!!}o' 
 a=MM""	!
 
 !!}o'  NN.2OO0
 Q-	 22MM,""$>	

 Q-
 	6  ",,.  Z!89CCE	
 '(#";#7#7#9#C#C#EF
#)
	 ))+++E2OO*3/H

	 UA&
''I**,<<ZHI
	
 335F IOPA9.>?PI	 ))+0AA0ECL??CTUaq{{#4q#89UGU6=>z!''),>G> w.II,J,J,LMq

NMN )* +BB  - Q V>Ms   
OO#.O(2O-c                   t        j                  d|ddf      }t        j                  dd|df      }t        j                  ddd|f      }t        j                  d| dz  |dz  dfgddg      }t        |t	        j                  |      j                  t        j                        g      }t        j                  d|dz  d	t        j                  t        j                  f
      j                  t        |dz              j                         }t        j                  d|dz  d	t        j                  t        j                  f
      j!                  t"        j$                  d      j                  t        |dz              j                         }t        j                  d|dz  d	t        j                  t        j                  f
      j!                  t"        j&                  d      j!                  t"        j(                  d      j                  t        |dz              j                         }	t+        ||||j-                  t        |dz              |j!                  t"        j$                  d      j-                  t        |dz              |j!                  t"        j&                  d      j-                  t        |dz              g|||	      }
|
S )z*The coordinate system triad (X, Y, Z axes))r   r   r   r         )r   r   )r   g      ?r   r      
singleline)r   r0   YZ   r   i)r1   	make_linemake_spliner2   copymirrorr*   XZrD   r   r"   MINr   mover)   r   r   r'   r   r   r   Curvemoved)rp   
axes_scalex_axisy_axisz_axis	arrow_arcarrowx_labely_labelz_labeltriads              rV   
make_triadzCompound.make_triad  sb    	J1+=>	Az1+=>	Aq*+=>$$*r):?A>?&
	 i9!5!<!<UXX!FGHZ!^\%))U\\9R   T(6A:&'UW 	 Z!^\%))U\\9R   VDFFBT(6A:&'UW 	 Z!^\%,,		9R   VDFFBVDFFBT(6A:&'UW 	 HVaZ01TVVR(..x
/CDTVVS)//!0DE
 
 
 

 rZ   c                   | j                   dk(  re| j                  
t               nt        | j                        }||z   }t	        |t
              rt        |g      }n|}| j                  |ddg       |S |t               }n%t        d t	        |t              r|gn|D              }|s| S t        d | j                         |z   D              }t        |      dk  r%t        j                  |dd | j                         }|S t               }|j                  t               | j                  |d   ddg       | j                  |dd |dd |      }t	        |t               s!t        j                  |g| j                         }|S )zCombine other to self `+` operator

        Note that if all of the objects are connected Edges/Wires the result
        will be a Wire, otherwise a Shape.
        r0   NrL   _NodeMixin__childrenc              3  N   K   | ]  }||j                         D ]  }|   y wr]   )r   )r`   r   shapes      rV   rb   z#Compound.__add__.<locals>.<genexpr>  s;      !=335	!  !!s   #%c              3  &   K   | ]	  }||  y wr]    r`   rS   s     rV   rb   z#Compound.__add__.<locals>.<genexpr>  s      
A
s   r   )rY   _wrappedr   rL   rK   r1   copy_attributes_tor5   r4   r   lenmake_compositer   SetFuzzyValuer&   _bool_oprD   )rR   othercurvesum1dresult1dsummandsresultfuse_ops           rV   __add__zCompound.__add__  sq    99>#}}4EG%:MEEME%& %> ##Hy:P.QRO = {H  !%/u%=5'5! H K 
002X=
 
 x=A!00!A		JF  '(G!!),##HQK)=S1TU]]8BQ<!"wGFfh/--vh		BrZ   c                
   t        j                  | |      }|
t               S t        |t              rt        j
                  |      }n&t        |t              st        j
                  |g      }| j                  |ddg       |S )z$Intersect other to self `&` operatorrL   r   )r4   __and__rD   rK   listr   r   )rR   r   intersections      rV   r   zCompound.__and__  sr    }}T51:lD) //=LL(3 //?Ly:P.QRrZ   c                h    | j                   duxr# t        | j                        j                         S )z!
        Check if empty.
        N)r   r   rL   MorerX   s    rV   __bool__zCompound.__bool__  s*    
 }}D(Q_T\\-J-O-O-QQrZ   c              #     K   t        | j                        }|j                         rGt        j	                  |j                                |j                          |j                         rFyyw)z*
        Iterate over subshapes.

        N)r   rL   r  rD   rs   ValueNext)rR   iterators     rV   __iter__zCompound.__iter__  sI      #4<<0mmo-- 011MMO mmos   A+A0.A0c                :    d}| j                   | D ]  }|dz  }	 |S )zReturn the number of subshapesr   r0   )r   )rR   count_s      rV   __len__zCompound.__len__  s.    ==$ 
rZ   c                   t        | d      r[t        | d      rO| j                  j                   dt        |       dd| j                   ddt        | j                         dz   }|S | j                  j                   dt        |       d}|S )	zReturn Compound info as stringrG   rQ   z at z#xz, label(z), z
#children())hasattrrU   __name__idrG   r   rQ   )rR   r   s     rV   __repr__zCompound.__repr__   s    4!gdJ&?>>**+44}HTZZLPSTs4==12!45   //0RXbMBFrZ   c                    t        j                  | |      }t        |t              st        j                  |g      }| j                  |ddg       |S )zCut other to self `-` operatorrL   r   )r4   __sub__rK   rD   r   r   )rR   r   
differences      rV   r  zCompound.__sub__+  sJ    ]]4/
*h/--zl;J
Y8N,OPrZ   c                \   |t         j                  k(  rt        d      |t         j                  k(  r\t	               }t
        j                  t        |          }|r. || j                  |       t        |j                               }|S t        | j                         j                         }|S )a  Return center of object

        Find center of object

        Args:
            center_of (CenterOf, optional): center option. Defaults to CenterOf.MASS.

        Raises:
            ValueError: Center of GEOMETRY is not supported for this object
            NotImplementedError: Unable to calculate center of mass of this object

        Returns:
            Vector: center
        z3Center of GEOMETRY is not supported for this object)r#   GEOMETRYr   MASSr   r4   shape_properties_LUTrA   rL   r+   CentreOfMassNotImplementedErrorr}   center)rR   	center_of
propertiescalc_functionmiddles        rV   r  zCompound.center4  s     )))RSS%%J!667J47PQMdllJ7
 7 7 9:
  *)&&(//1FrZ   c                h    | j                         }t        |      }|dk7  rt        d|       |d   S )zReturn the Compoundr0   z%Expected exactly one compound, found r   )	compoundsr   r   )rR   
shape_listentity_counts      rV   compoundzCompound.compoundQ  s<    ^^%
:1D\NSTT!}rZ   c                   | j                   
t               S t        | j                  t              rF| D cg c]  }t        |j                  t              s|! }}|j                  |        t        |      S g }t        |      S c c}w )z+compounds - all the compounds in this Shape)r   r5   rK   rL   r   append)rR   csub_compoundss      rV   r#  zCompound.compoundsY  su    == ;dllO4(,W1
199o0VQWMW  & '' M''	 Xs   BBc           	     ^   t        t        |             }|s|j                  d       |D cg c]%  }t        j                  |j                               ' }}t        t        t        t        |                  d      D cg c]  }t        t        t        |             }}|D ]|  }||d      j                  ||d            }	|	#||d      j                  ||d            }
|
Ct        d |
j                         D              }||kD  sid||d      ||d      f|fc S  yc c}w c c}w )aC  Do Children Intersect

        Determine if any of the child objects within a Compound/assembly intersect by
        intersecting each of the shapes with each other and checking for
        a common volume.

        Args:
            include_parent (bool, optional): check parent for intersections. Defaults to False.
            tolerance (float, optional): maximum allowable volume difference. Defaults to 1e-5.

        Returns:
            tuple[bool, tuple[Shape, Shape], float]:
                do the object intersect, intersecting objects, volume of intersection
        r   r{   r0   c              3  4   K   | ]  }|j                     y wr]   r^   r   s     rV   rb   z1Compound.do_children_intersect.<locals>.<genexpr>  s     'TQ'Trc   T)F)NNrx   )r   r!   popr<   from_bounding_boxr}   r   ranger   tuplemapint	intersectrd   solids)rR   include_parent	tolerancerQ   childchildren_bboxcombchild_index_pairschild_index_pairbbox_intersectionobj_intersectioncommon_volumes               rV   do_children_intersectzCompound.do_children_intersecte  so   " !%\$%7 8LLO HP
>CE##E$6$6$89
 

 %T%H*>%?C
 #c4.!
 
 !2 	 !..>q.A B L L.q12! !,#+,<Q,?#@#J#J-a01$  $/$''T:J:Q:Q:S'T$TM$y0  ()9!)< = ()9!)< = *  	* *9

s   *D% D*c                   t         t        j                  t        t        j                  t
        t        j                  t        t        j                  t        t        j                  t        t        j                  t        t        j                  i}g }| j                         D ]  }t!               }|j#                  |j$                         |j'                         s9|j)                         }|j+                         ||   k(  r |j-                   |t/        |                   |j1                          |j'                         rg |S )a  get_type

        Extract the objects of the given type from a Compound. Note that this
        isn't the same as Faces() etc. which will extract Faces from Solids.

        Args:
            obj_type (Union[Vertex, Edge, Face, Shell, Solid, Wire]): Object types to extract

        Returns:
            list[Union[Vertex, Edge, Face, Shell, Solid, Wire]]: Extracted objects
        )rB   r   rh   r1   ri   r=   rk   r>   rl   r<   rm   r2   rj   rD   rn   r#  r   
InitializerL   r  r  	ShapeTyper(  r7   r  )rR   obj_typetype_mapresultscompr  r7  s          rV   re   zCompound.get_type  s    0 $22".."..#00#00"..&66
 NN$ 	 D&(H---/ (??$(::NN8HUO#<=	 --/	  rZ   c                `   t        |t              rt        |      }n]t        |t              rt        |j                        }n7t        |t
              rt        |      }nt        |t              rt        |      }| j                  r| j                  n
t        |       }|syt               }t        |t              r$|j                  r|j                  n
t        |      }n|g}|D ]0  }|D ])  }|j                  |||      }	|	s|j                  |	       + 2 t        t        |            }
|
r|
S dS )u  Single-object intersection for Compound (OR semantics).

        Distributes intersection over elements, collecting all results:
            Compound([a, b]).intersect(s) = (a ∩ s) ∪ (b ∩ s)
            Compound([a, b]).intersect(Compound([c, d])) = (a ∩ c) ∪ (a ∩ d) ∪ (b ∩ c) ∪ (b ∩ d)

        Handles both build123d assemblies (children) and OCCT Compounds (list()).
        Nested Compounds are handled by recursion.

        Args:
            other: Shape or geometry object to intersect with
            tolerance: tolerance for intersection detection
            include_touched: if True, include boundary contacts
                (only relevant when Solids are involved)
        N)rK   r+   rB   r)   r   r'   r1   r*   r=   rQ   r   r5   rD   
_intersectextendset)rR   r   r6  include_touchedself_elementsrE  other_elements	self_elem
other_elemr  uniques              rV   rH  zCompound._intersect  s   , eV$5MEx(5>>*Et$KEu%KE *.DJ&[ eX&/4~~U^^4;N#WN& 	1I, 1
(33	?   NN<01	1 3w<(v)T)rZ   c                    t               }| j                  r| j                  n
t        |       }|D ]#  }|j                  |j	                  ||             % t        t        |            S )a  Distribute touch over compound elements.

        Iterates over elements and collects touch results. Only Solid and
        Face elements produce boundary contacts; other shapes return empty.

        Args:
            other: Shape to check boundary contacts with
            tolerance: tolerance for contact detection

        Returns:
            ShapeList of boundary contact geometry (empty if no contact)
        )r5   rQ   r   rI  touchrJ  )rR   r   r6  rE  elementselems         rV   rR  zCompound.touch  sY     '[ %)MM4==tDz 	9DNN4::eY78	9 W&&rZ   c                4    t        j                  | ||||      S )a  project_to_viewport

        Project a shape onto a viewport returning visible and hidden Edges.

        Args:
            viewport_origin (VectorLike): location of viewport
            viewport_up (VectorLike, optional): direction of the viewport y axis.
                Defaults to (0, 0, 1).
            look_at (VectorLike, optional): point to look at.
                Defaults to None (center of shape).
            focus (float, optional): the focal length for perspective projection
                Defaults to None (orthographic projection)

        Returns:
            tuple[ShapeList[Edge],ShapeList[Edge]]: visible & hidden Edges
        )r3   project_to_viewport)rR   viewport_originviewport_uplook_atfocuss        rV   rV  zCompound.project_to_viewport  s"    . **/;
 	
rZ   c                &   t        |       dk(  rt        t        |             }| j                  |ddg       t	        |t
              rD|j                  |      }|s t        |       |j                        }| j                  |ddg       |S |r|S | S | S )a  Strip unnecessary Compound wrappers

        Args:
            fully (bool, optional): return base shape without any Compound
                wrappers (otherwise one Compound is left). Defaults to True.

        Returns:
            Union[Self, Shape]: base shape
        r0   rL   r   )	r   nextiterr   rK   rD   unwraptyperL   )rR   fullysingle_element	unwrappeds       rV   r^  zCompound.unwrap2  s     t9>!$t*-N##NY@V4WX .(3*11%8	 *T
9+<+< =I''	I?U3VW  %*>44 rZ   c                    t        j                  d| j                  |j                         t        |j                  D cg c]  }|j
                   c}      |_        yc c}w )z(Method call after attaching to `parent`.zUpdated parent of %s to %sN)r-   debugrG   r:   rQ   rL   rR   rI   r)  s      rV   _post_attachzCompound._post_attachN  s@    14::v||L: &01QYY0
0s   Ac                   |r}dj                  |D cg c]  }|j                   c}      }t        j                  d|| j                         t	        | j
                  D cg c]  }|j                   c}      | _        yyc c}w c c}w )z'Method call after attaching `children`.,zAdding children %s to %sNjoinrG   r-   rd  r:   rQ   rL   rR   rQ   r7  kidsr)  s        rV   _post_attach_childrenzCompound._post_attach_childrenU  sf    88h?UU[[?@DLL3T4::F<$(MM2q2DL ? 3   B Bc                    t        j                  d| j                  |j                         |j                  r3t	        |j                  D cg c]  }|j
                   c}      |_        yyc c}w )z*Method call after detaching from `parent`.zRemoving parent of %s (%s)N)r-   rd  rG   rQ   r:   rL   re  s      rV   _post_detachzCompound._post_detach`  sL    14::v||L??>$*OO4q4FN 4s   A,c                   |r}dj                  |D cg c]  }|j                   c}      }t        j                  d|| j                         t	        | j
                  D cg c]  }|j                   c}      | _        yyc c}w c c}w )z(Method call before detaching `children`.rh  zRemoving children %s from %sNri  rk  s        rV   _post_detach_childrenzCompound._post_detach_childrenj  sf    88h?UU[[?@DLL7tzzJ<$(MM2q2DL ? 3rn  c                :    t        |t              st        d      y)z)Method call before attaching to `parent`.z!`parent` must be of type CompoundN)rK   rD   r   )rR   rI   s     rV   _pre_attachzCompound._pre_attachu  s    &(+@AA ,rZ   c                >    t        d |D              st        d      y)z(Method call before attaching `children`.c              3  <   K   | ]  }t        |t                y wr]   )rK   r4   )r`   r7  s     rV   rb   z0Compound._pre_attach_children.<locals>.<genexpr>|  s     B:eU+Bs   z Each child must be of type ShapeN)allr   )rR   rQ   s     rV   _pre_attach_childrenzCompound._pre_attach_childrenz  s"    BBB?@@ CrZ   c                f    t               }|j                  | j                  |j                         | S )z]Return self with the specified shape removed.

        Args:
          shape: Shape:
        )r   RemoverL   )rR   r   comp_builders      rV   _removezCompound._remove  s)     &'DLL%--8rZ   )NrJ   NrJ   NNN)rF   z(TopoDS_Compound | Iterable[Shape] | NonerG   strrH   zColor | NonerO   r}  rP   zdict[str, Joint] | NonerI   zCompound | NonerQ   zSequence[Shape] | None)r   z
int | None)r   r   )rF   r    r   z6Vertex | Edge | Wire | Face | Shell | Solid | Compound)rF   r>   ru   r,   r   rD   )r   r}  r   r   r   r}  r   zPathLike[str] | str | Noner   r$   r   ztuple[TextAlign, TextAlign]r   z"Align | tuple[Align, Align] | Noner   r   r   zEdge | Wire | Noner   r   r   rD   )r   r   r   rD   )r   None | Shape | Iterable[Shape]r   zCompound | Wire)r   zShape | Iterable[Shape]r   rD   )r   bool)r   zIterator[Shape]r   r2  )r   r~  r   rD   )r  r#   r   r+   )r   rD   )r   zShapeList[Compound])Fgh㈵>)r5  r  r6  r   r   z5tuple[bool, tuple[Shape | None, Shape | None], float])rC  zOtype[Vertex] | type[Edge] | type[Face] | type[Shell] | type[Solid] | type[Wire]r   z1list[Vertex | Edge | Face | Shell | Solid | Wire])ư>F)r   z(Shape | Vector | Location | Axis | Planer6  r   rK  r  r   zShapeList | None)r  )r   r4   r6  r   r   zShapeList[Vertex | Edge | Face])r|   NN)
rW  r,   rX  r,   rY  zVectorLike | NonerZ  zfloat | Noner   z'tuple[ShapeList[Edge], ShapeList[Edge]])T)r`  r  r   zSelf | Shape)rI   rD   )rQ   zIterable[Shape])r   r4   r   rD   ),r  
__module____qualname____doc__orderrN   propertyrY   r_   classmethodrs   rv   r$   REGULARr%   r   r   r   r   r   r  r	  r  r  r  r#   r  r  r&  r#  r?  re   rH  rR  rV  r^  rf  rm  rp  rr  rt  rx  r|  __classcell__)rU   s   @rV   rD   rD   z   s   J E 9="*."&+/%=5%= %= 	%=
 %= (%=  %= )%=R ( ( U U ::	?: :* X X" 
 04 ) 1 13<3C3CYEUEU2V48"%(,#&mm m 	m
 .m m 0m 2m  m &m !m 
m m^ 0 0h,\
R
	 ,4== :
( @D1*"1*7<1*	>1*f** 
;*^   %	8*78* 8* 	8*
 
8*v 04''','	('8 #,%)"
#
  
 #	

 
 
1
68
B
A
rZ   rD   c                  Z    e Zd ZdZej
                  Zedd       Zd	dZd	dZ	d
dZ
ddZy)r   z,A Compound containing 1D objects - aka Edgesc                     y)Nr0   r   rX   s    rV   rY   z
Curve._dim      rZ   c                R    t        | j                               j                  |      S )z7Position on curve operator @ - only works if continuous)r2   r   r   rR   r   s     rV   
__matmul__zCurve.__matmul__      DJJL!--h77rZ   c                R    t        | j                               j                  |      S )z5Tangent on wire operator % - only works if continuous)r2   r   r   r  s     rV   __mod__zCurve.__mod__  s    DJJL!,,X66rZ   c                R    t        | j                               j                  |      S )z6Location on wire operator ^ - only works if continuous)r2   r   location_atr  s     rV   __xor__zCurve.__xor__  r  rZ   c                H    t        j                  | j                               S )z&A list of wires created from the edges)r2   r   r   rX   s    rV   wireszCurve.wires  s    ||DJJL))rZ   Nr  )r   r   r   r+   )r   r   r   r)   )r   zShapeList[Wire])r  r  r  r  r3   r   r  rY   r  r  r  r  r   rZ   rV   r   r     s6    6ooG  
878*rZ   r   c                  *    e Zd ZdZedd       ZddZy)Sketchz,A Compound containing 2D objects - aka Facesc                     y)Nr{   r   rX   s    rV   rY   zSketch._dim  r  rZ   c                    | |z   S r]   r   rR   r   s     rV   __iadd__zSketch.__iadd__      e|rZ   Nr  )r   r~  r   r  r  r  r  r  r  rY   r  r   rZ   rV   r  r    s    6  rZ   r  c                  *    e Zd ZdZedd       ZddZy)Partz-A Compound containing 3D objects - aka Solidsc                     y)N   r   rX   s    rV   rY   z	Part._dim  r  rZ   c                    | |z   S r]   r   r  s     rV   r  zPart.__iadd__  r  rZ   Nr  )r   r~  r   r  r  r   rZ   rV   r  r    s    7  rZ   r  r{   r  )br  
__future__r   r   warningscollections.abcr   r   r   	itertoolsr   osr   r	   typingr
   typing_extensionsr   
OCP.TopAbsTopAbsrg   OCP.BRepAlgoAPIr   r   r   OCP.gpr   OCP.Graphic3dr   r   r   r   r   r   r   	OCP.GPropr   OCP.NCollectionr   
OCP.StdPrsr   r   r   r   
OCP.TopoDSr   r   r   r   r    anytreer!   build123d.build_enumsr"   r#   r$   r%   build123d.geometryr&   r'   r(   r)   r*   r+   r,   r-   build123d.textr.   r/   one_dr1   r2   r3   
shape_corer4   r5   r6   r7   r8   r9   r:   three_dr;   r<   two_dr=   r>   utilsr?   r@   rA   zero_drB   rD   r   r  r  register_composite_factoryr   rZ   rV   <module>r     s(  4l #   8 8 "   "  U U    # 2 V '  ! G G	 	 	 4 & &   $  
 Mw' M`*H *:
X 

8 
 !    x 0      E *      F +      D )rZ   