
    ^j9d              	         d 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
mZmZ ddlmZ ddlmZmZ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mZmZm Z  dd	l!m"Z"m#Z#m$Z$m%Z% 	 	 	 	 	 	 	 	 dd
Z&dddddddde	jN                  f		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ(ddde	jN                  f	 	 	 	 	 	 	 	 	 ddZ)dejT                  ejV                  de	jN                  f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ,	 	 	 	 	 	 	 	 	 	 ddZ-dej\                  dde	jN                  f	 	 	 	 	 	 	 	 	 	 	 ddZ/dej`                  dde	jb                  f	 	 	 	 	 	 	 	 	 	 	 ddZ2ddddde	jN                  f	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ3y)a  
Part Operations

name: operations_part.py
by:   Gumyr
date: March 17th 2023

desc:
    This python module contains operations (functions) that work on Parts.

license:

    Copyright 2023 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.

    )annotations)cast)Iterable)GeomTypeModeUntilKindSide)	BuildPart)AxisPlaneVector
VectorLike)CompoundCurveDraftAngleErrorEdgeFaceShellSolidWirePartSketch	ShapeListVertex)loggerWorkplaneListflatten_sequencevalidate_inputsc           	     x   t        j                  d      }t        |       }t        d |D              sJ d       t	        |d|       t
        j                  t
        j                  t
        j                  h}|D cg c]  }|j                  |vs| }}|r-t        ddj                  t        d |D                           t        d |D              }t        |      dk7  rt        d	      t        t        |            j!                         }	t        |	      dk7  rt        d
      	 |	d   j#                  |||      }
|"|j+                  |
dt,        j.                         t1        t3        |
g      j4                        S c c}w # t$        $ r(}t%        d|j&                  |j(                        |d}~ww xY w)a	  Part Operation: draft

    Apply a draft angle to the given faces of the part

    Args:
        faces: Faces to which the draft should be applied.
        neutral_plane: Plane defining the neutral direction and position.
        angle: Draft angle in degrees.
    draftc              3  <   K   | ]  }t        |t                y wN)
isinstancer   .0fs     R/opt/ringagent/.cad-venv/lib/python3.12/site-packages/build123d/operations_part.py	<genexpr>zdraft.<locals>.<genexpr>L   s     6qz!T"6   zall faces must be of type Facez.Draft not supported on face(s) with geometry: z, c              3  H   K   | ]  }|j                   j                    y wr#   )	geom_typenamer%   s     r(   r)   zdraft.<locals>.<genexpr>T   s     C!Q[[--Cs    "c              3  N   K   | ]  }|j                   |j                     y wr#   )topo_parentr%   s     r(   r)   zdraft.<locals>.<genexpr>X   s     U1==;Tq}}Us   %%   z:All faces must share the same topological parent (a Solid)z)Topological parent must be a single Solidr   zXDraft operation failed. Use `err.face` and `err.problematic_shape` for more information.)faceproblematic_shapeNFcleanmode)r   _get_contextr   allr   r   PLANECYLINDERCONEr,   
ValueErrorjoinsetlennextitersolidsr!   r   r1   r2   _add_to_contextr   REPLACEr   r   wrapped)facesneutral_planeanglecontext	face_listvalid_geom_typesr'   unsupportedtopo_parentsparent_solids	new_soliderrs               r(   r!   r!   ;   s    !* 6 6w ?G!1%!8I6I66X8XX6GWi0 (9(98==I'O1;;>N+N1OKO<yyC{CCDEG
 	
 UiUUL
<AUVVl+,335M
=QDEE!!$**9mUK	 	T\\J)%--..; P$  O!33	

 	s$   :FF*F 	F9#F44F9NFg        Tc	           
     (   t        j                  d      }	t        |	d|        | @|	3|	j                  r'|	j                  }
|	j                  }g |	_        g |	_        nct        d      t        | t        t        t        f      rg | n| j                         }
g }|
D ]"  }	 t        |      }||j                  |       $ g }|O|
D cg c]D  }t        |j                         |j                  j                  j                   t#        |            F }}t%        |      t%        |
      k7  rt        d      t'        j(                  dt%        |
      t%        |             t+        |
|      D ]  \  }}|rddgndgD ]  }|t|dk(  r7|j                  t-        j.                  ||j0                  |z  |z  	             A|j                  t-        j2                  ||j0                  |z  |z  |
             y|t        d      ||	t        d      |	j4                  }n|}|t        d      |j                  t-        j6                  |||j0                  |z  |               |r@t%        |      dkD  r2 |j9                         j:                  | }t        |t              r|n|g}|r|D cg c]  }|j=                          }}|	 |	j>                  |||d tA        tC        |      jE                               S # t
        $ r d}Y _w xY wc c}w c c}w )a  Part Operation: extrude

    Extrude a sketch or face by an amount or until another object.

    Args:
        to_extrude (Union[Face, Sketch], optional): object to extrude. Defaults to None.
        amount (float, optional): distance to extrude, sign controls direction. Defaults to None.
        dir (VectorLike, optional): direction. Defaults to None.
        until (Until, optional): extrude limit. Defaults to None.
        target (Shape, optional): extrude until target. Defaults to None.
        both (bool, optional): extrude in both directions. Defaults to False.
        taper (float, optional): taper angle. Defaults to 0.0.
        clean (bool, optional): Remove extraneous internal structure. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD.

    Raises:
        ValueError: No object to extrude
        ValueError: No target object

    Returns:
        Part: extruded object
    extrudeN!A face or sketch must be providedz4dir must be provided when extruding non-planar facesz)%d face(s) to extrude on %d face plane(s)r0   r   )	direction)rT   taperz'Either amount or until must be providedz A target object must be providedzNo target object provided)targetrT   untilr3   )#r   r6   r   pending_facespending_face_planesr;   r$   tuplelistfilterrE   r   appendcentercenter_locationx_axisrT   r   r>   r   infozipr   rQ   z_dirextrude_taperpartextrude_untilpopfuser4   rB   r   r   rA   )
to_extrudeamountdirrW   rV   bothrU   r4   r5   rH   to_extrude_facesface_planesr1   plane
new_solidsrT   target_objectfused_solidssolids                      r(   rQ   rQ   p   s.   D !* 6 6y AGGY
3 7#8#8&44!55K$&G!*,G'@AA
 *udF&;< jM!!# 	
 $ 	*Dd  ""5)	* !J
 )
 $++-!5!5!<!<!F!FsT
 
 ;3/00OPP
KK3K +[9 &e$(!Rqc %	I!A:%% &+kkF&:Y&F %%++ &+kkF&:Y&F"' =$%NOO>()KLL$+LLM$*M ($%@AA!!'',"'++	"9#	=%	&P J!#,z~~',,j9%/d%C\,
1;<ekkm<
<5tD	*%,,.//O  
r =s   K8A	L
(L8LLc           	     ,   d }t        j                  d      }t        |       }t        |d|       t	        d |D              r4||j
                  st        d      |j
                  }g |_        g |_        n|}t        d |D              rQt        |d   t              st        |d   t              st        d	      t        d
 |dd D              rt        d	      g }g }	|D ]w  }
t        |
t              r|j                  |
       %|
j                         D ]@  }|j                  |j                                |	j                  |j                                B y  ||	      }t        j                   ||      }|r3t#        t        |j%                  t        j                   ||                  }|j&                  sq	 |j                         |D 
cg c]  }
t        |
t(              s|
 c}
z   }t        t+        |            }|r|j-                         }|j&                  st        d      	 ||j3                  |||       n|r|j-                         }t5        t7        |g      j8                        S c c}
w # t.        $ r}t1        d      |d}~ww xY w)aB  Part Operation: loft

    Loft the pending sketches/faces, across all workplanes, into a solid.

    Args:
        sections (Vertex, Face, Sketch): slices to loft into object. If not provided, pending_faces
            will be used. If vertices are to be used, a vertex can be the first, last, or
            first and last elements.
        ruled (bool, optional): discontiguous layer tangents. Defaults to False.
        clean (bool, optional): Remove extraneous internal structure. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD.
    c                    | D ch c]  }t        |       }}|dhk  rg S |dhk(  r| D cg c]  }|d   	 c}S t        |      dkD  rt        d      t        dt        |       d      c c}w c c}w )Nr   r0   z4The number of holes in the sections must be the samezJloft supports a maximum of 1 hole per section but one or more section has zF hole - loft the perimeter and holes separately and subtract the holes)r>   r;   max)lstsublengthss      r(   normalize_list_of_listsz%loft.<locals>.normalize_list_of_lists  s    '*+3s8++qc>Iqc>&)*sCF**w<!STTw<. !!"
 	
 , +s
   A+A0loftc              3  $   K   | ]  }|d u  
 y wr#    r&   ss     r(   r)   zloft.<locals>.<genexpr>  s     
+19
+s   NzNo sections providedc              3  <   K   | ]  }t        |t                y wr#   r$   r   r~   s     r(   r)   zloft.<locals>.<genexpr>&  s     
9Q:a 
9r*   r   rS   z<Vertices must be the first, last, or first and last elementsc              3  <   K   | ]  }t        |t                y wr#   r   r~   s     r(   r)   zloft.<locals>.<genexpr>-  s     Cz!V$Cr*   r0   zRecovery failedzFailed to create valid loftr3   )r   r6   r   r   r7   rX   r;   rY   anyr$   r   r]   rE   
outer_wireinner_wiresr   	make_loftr   cutis_validr   r   r4   	ExceptionRuntimeErrorrB   r   r   rD   )sectionsruledr4   r5   rz   rH   section_listinput_sectionsloft_sectionshole_candidatesr   r1   holesrN   recovery_faceses                   r(   r{   r{      sy   &
 !* 6 6v >G#H-LGV\2 
+l
++?'"7"7344 .. "&(#% 
9.
99.+V4Z2>
 N  CnQr.BCCN 
 MO ;a   #	 ;$$T__%67&&t'7'7'9:;	; $O4E u5I	eooeU.K LM	 
	E&__.(2Jq$,?2 N eN34I%OO-	%% !233 &
 	TB	OO%	)%--..!2  	E<=1D	Es1   <I9 I4%I4)AI9 4I9 9	JJJc           	        t        j                  d      }t        |d       |Et        |t              r|j                         d   }nGt        |t        t        f      s1t        d      ||j                  |j                  }nt        d      |j                  | ||d      }|j                         }		 t        t        |            }
t               }|j                         }t        |t         t"        f      r|gt%        |      z  }n't        |t&              rt)        |      }nt+        d	      |D ]t  }|	j-                  t/        |            }|d
d D ]P  }t1        t/        ||z
        j2                  | z
        dk  s+|j5                  t        j6                  ||              t v |j9                  |      }t%        |      t%        |      k7  rt        dt%        |       d      t;        ||      D cg c])  \  }}t        j<                  ||
j>                  |z        + }}}|jA                         j9                  |      }g }tC        t%        |      d
z
        D ]6  }|j5                  tE        jF                  ||   ||d
z      g||                8 t%        |      d
kD  r!tI        tJ        tK        jL                  |       }n|d   }|$|jO                  |||       t               |_(        n|r|jS                         }tK        tU        |g      jV                        S # t        $ r}t        d      |d}~ww xY wc c}}w )a  make_brake_formed

    Create a part typically formed with a sheet metal brake from a single outline.
    The line parameter describes how the material is to be bent. Either a single
    width value or a width value at each vertex or station is provided to control
    the width of the end part.  Note that if multiple values are provided there
    must be one for each vertex and that the resulting part is composed of linear
    segments.

    Args:
        thickness (float): sheet metal thickness
        station_widths (Union[float, Iterable[float]]): width of part at
            each vertex or a single value. Note that this width is perpendicular
            to the provided line/plane.
        line (Union[Edge, Wire, Curve], optional): outline of part. Defaults to None.
        side (Side, optional): offset direction. Defaults to Side.LEFT.
        kind (Kind, optional): offset intersection type. Defaults to Kind.ARC.
        clean (bool, optional): clean the resulting solid. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD.

    Raises:
        ValueError: invalid line type
        ValueError: not line provided
        ValueError: line not suitable
        ValueError: incorrect # of width values

    Returns:
        Part: sheet metal part
    make_brake_formedNr   z)line must be either a Curve, Edge or WirezA line must be providedT)distancekindsideclosedz%line not suitable - probably straightz<station_widths must be either a single number or an iterabler0   g{Gz?z^widths must either be a single number or an iterable with a length of the # vertices in line ())objrT   )pathr3   ),r   r6   r   r$   r   wiresr   r   r;   pending_edges_as_wire	offset_2dverticesr   r   r   r   floatintr>   r   r[   	TypeErrorsort_by_distancer   abslengthr]   	make_linesort_byrb   rQ   rc   edgesranger   sweep_multir   r   rh   rB   pending_edgesr4   r   rD   )	thicknessstation_widthsliner   r   r4   r5   rH   offset_lineoffset_verticesro   excstation_edgesline_verticesstation_widths_listvertexothersotherr   wstation_facessweep_pathsr   irN   s                            r(   r   r   [  s!   N !* 6 67J KGG01dE"::<?DD4,/HII		!>!>!J,,233 ..)$TRV.WK!**,OKd;'(
 &/[MMMOM.5#,/-.]1CC	NH	-">2VWW  11&.AABZ 	E66E>+22Y>?$F$$T^^FE%BC	 "))$/M
3}#55336}3E2FaI
 	
 ':;Aq 	ekkAo6M  **,&&t,KH3}%)* 
q!=Q#78{1~	

 8}qtyy(34	QK		TB )	OO%	)%--..e  K@AsJK6s   5L% 8.M%	L?.L::L?c                   t        j                  d      }|t        |t               st        d      t        | t              rt        |       n
t        |       } t        |      j                         }t        |      j                         }| ||z  z   }t        ||      }t        j                  dd|      }t        | |z   |      }|j                  |      }	|	st        d      |	d   d   |z
  }
|
|_        |S )a
  Part Operation: project_workplane

    Return a plane to be used as a BuildSketch or BuildLine workplane
    with a known origin and x direction. The plane's origin will be
    the projection of the provided origin (in 3D space). The plane's
    x direction will be the projection of the provided x_dir (in 3D space).

    Args:
        origin (Union[VectorLike, Vertex]): origin in 3D space
        x_dir (Union[VectorLike, Vertex]): x direction in 3D space
        projection_dir (VectorLike): projection direction
        distance (float): distance from origin to workplane

    Raises:
        RuntimeError: Not suitable for BuildLine or BuildSketch
        ValueError: x_dir perpendicular to projection_dir

    Returns:
        Plane: workplane aligned for projection
    project_workplanezIprojection_workplane can only be used from a BuildPart context or algebra)rc   g    eA)ro   z%x_dir perpendicular to projection_dirr   )r   r6   r$   r   r   r   
normalizedr   r   	make_rectr   find_intersection_pointsr;   x_dir)originr   projection_dirr   rH   workplane_origin	workplanescreenx_dir_point_axis
projectionworkplane_x_dirs              r(   r   r     s    4 !* 6 67J KG:gy#AW
 	
  *&&9VF^vf~F5M$$&EN+668N  99&n=I ^^CI6FFUNN;001ABJ@AA !mA&)99O%IO         v@c                D   t        j                  d      }t        |       }t        |d|       |dk\  rdnd}||dz  z  }|dk(  r|dz  n|}t	        |D 	cg c]  }	|	du  c}	      r6|||j
                  st        d      |j
                  }
g |_        g |_        n|j                         }
|
D cg c]  }t        j                  |||       }}t        |      }| |j                  |||d n|r|j                         }t        |j                        S c c}	w c c}w )	a  Part Operation: Revolve

    Revolve the profile or pending sketches/face about the given axis.
    Note that the most common use case is when the axis is in the same plane as the
    face to be revolved but this isn't required.

    Args:
        profiles (Face, optional): 2D profile(s) to revolve.
        axis (Axis, optional): axis of rotation. Defaults to Axis.Z.
        revolution_arc (float, optional): angular size of revolution. Defaults to 360.0.
        clean (bool, optional): Remove extraneous internal structure. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD.

    Raises:
        ValueError: Invalid axis of revolution
    revolver   r0   rS   r   NzNo profiles providedr3   )r   r6   r   r   r7   rX   r;   rY   rE   r   r   r   rB   r4   r   rD   )profilesaxisrevolution_arcr4   r5   rH   profile_listsignrG   r   profile_facesprofilerp   rN   s                 r(   r   r     s&   . !* 6 6y AG#H-LGY5 !#1DdUl+E!QJD5LEE
|,!AI,-?w27;P;P344-- "&(#$**,ERS'%--5SJS$I5tD	OO%		!!""# - Ts   D0Dc                6   t        j                  d      }t        |dd       | | }n&||j                  |j                  }nt	        d      |j                  d      }t        d t        |j                        t        |j                        z   D              |j                  z   }|t        |t              r|n|g}	n,|t        j                         j                  }	nt	        d      |	D 
cg c]N  }
t        j                  d|z  d|z  t!        |
j"                  |
j$                  |z  z   |
j$                  	            P }}
| &||j&                  |j                  } nt	        d
      g }|D ]I  }
|j)                  |
      }t        |t*              r|j-                  |       6|9|j/                  |       K | |j0                  |d||d n|r|D cg c]  }|j3                          }}t5        t7        |      j8                        S c c}
w c c}w )a  Part Operation: section

    Slices current part at the given height by section_by or current workplane(s).

    Args:
        obj (Part, optional): object to section. Defaults to None.
        section_by (Plane, optional): plane(s) to section object.
            Defaults to None.
        height (float, optional): workplane offset. Defaults to 0.0.
        clean (bool, optional): Remove extraneous internal structure. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.INTERSECT.
    sectionNzNo object to sectionF)optimalc              3  2   K   | ]  }t        |        y wr#   )r   )r&   vs     r(   r)   zsection.<locals>.<genexpr>V  s     Ca3q6Cs   z&Plane(s) must be provide to section by   )r   rc   zobj must be provided)faces_to_pendingr4   r5   )r   r6   r   re   r;   bounding_boxrv   r[   mindiagonalr$   r   r   
workplanesr   r   r   r   rc   _obj	intersectr   extendr]   rB   r4   r   r   rD   )r   
section_byheightr4   r5   rH   
to_sectionbboxmax_sizesection_planesro   planesnew_objectsintersectionrs                  r(   r   r   8  s   & !* 6 6y AGGY-

		!9\\
/00""5"1DC4>DN#BCCdmmSH$Z:J 	 
	&335@@ABB $  	LLf(<<EKKP	
F  {7<<#;,,C344&(K -!++E2lI.|,%|,- 5D	
 .9:1779:K:(;'//00=8 ;s   0AHHc                2   t        j                  d      }t        |d|        |t        d      | 4|'|j                  r|j                  }g |_        g |_        n:t        d      t        | t        t        t        f      rg | n| j                         }g }t        j                  dt        |             |D ]W  }	||n|	j                         }
|rddgndgD ]5  }|j                  t!        j"                  |	|t%        |
      |z               7 Y | |j&                  |||d nNt        |      dkD  r!t)        t*        t+        j,                  |       g}|r|D cg c]  }|j/                          }}t+        t1        |      j2                        S c c}w )	a  Part Operation: thicken

    Create a solid(s) from a potentially non planar face(s) by thickening along the normals.

    Args:
        to_thicken (Union[Face, Sketch], optional): object to thicken. Defaults to None.
        amount (float): distance to extrude, sign controls direction.
        normal_override (Vector, optional): The normal_override vector can be used to
            indicate which way is 'up', potentially flipping the face normal direction
            such that many faces with different normals all go in the same direction
            (direction need only be +/- 90 degrees from the face normal). Defaults to None.
        both (bool, optional): thicken in both directions. Defaults to False.
        clean (bool, optional): Remove extraneous internal structure. Defaults to True.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD.

    Raises:
        ValueError: No object to extrude
        ValueError: No target object

    Returns:
        Part: extruded object
    thickenzAn amount must be providedrR   z%d face(s) to thickenr0   rS   )depthnormal_overrider3   )r   r6   r   r;   rX   rY   r$   rZ   r[   r\   rE   r   ra   r>   	normal_atr]   r   r   r   rB   r   r   rh   r4   r   rD   )
to_thickenrj   r   rl   r4   r5   rH   to_thicken_facesrp   r1   face_normalrT   rs   s                r(   r   r     s   < !* 6 6y AGGY
3 ~5667#8#8&44$&G!*,G'@AA
 *udF&;< jM!!# 	 !J
KK'-=)>?  	.:O@P 	 %)!Rqc 	I{8Ki8W			 5tDz?QtTYY
%;<=J5?@E%++-@J@$,,-- As   F)rE   zFace | Iterable[Face]rF   r   rG   r   returnr   )ri   Face | Sketch | Nonerj   float | Nonerk   VectorLike | NonerW   zUntil | NonerV   zCompound | Solid | Nonerl   boolrU   r   r4   r   r5   r   r   r   )
r   z7Face | Sketch | Iterable[Vertex | Face | Sketch] | Noner   r   r4   r   r5   r   r   r   )r   r   r   zfloat | Iterable[float]r   zEdge | Wire | Curve | Noner   r
   r   r	   r4   r   r5   r   r   r   )
r   VectorLike | Vertexr   r   r   r   r   r   r   r   )r   zFace | Iterable[Face] | Noner   r   r   r   r4   r   r5   r   r   r   )r   zPart | Noner   zPlane | Iterable[Plane]r   r   r4   r   r5   r   r   r   )r   r   rj   r   r   r   rl   r   r4   r   r5   r   r   r   )4__doc__
__future__r   typingr   collections.abcr   build123d.build_enumsr   r   r   r	   r
   build123d.build_partr   build123d.geometryr   r   r   r   build123d.topologyr   r   r   r   r   r   r   r   r   r   r   r   build123d.build_commonr   r   r   r   r!   ADDrQ   r{   LEFTARCr   r   Zr   XZPRIVATEr   r   r}   r   r(   <module>r     s  8 #  $ C C * > >    2/ 2/2/ 2/ 
	2/l (,!&*B0$B0B0 
B0 	B0
 $B0 B0 B0 B0 B0 
B0L IM	c/Ec/c/ c/ 	c/
 
c/R (,l/l/+l/ %l/ 	l/
 l/ l/ l/ 
l/^444 4 	4
 4p .2!4#*4#
4# 4# 	4#
 4# 
4#p */((G1	G1'G1 G1 	G1
 G1 G1V (,)-M.$M.M. 'M. 	M.
 M. M. 
M.r   