
    ^jt                        d Z ddlmZ ddlmZ ddl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mZmZmZmZ dd	lmZmZmZmZ  G d
 de      Z G d de      Z G d de      Z G d de      Z G d de      Zy)a  
build123d joints

name: joints.py
by:   Gumyr
date: August 24, 2023

desc:
    This python module contains all of the Joint derived classes.

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)inf)overload)validate_inputs)Align)	BuildPart)AxisLocationPlaneRotationRotationLikeVector
VectorLike)CompoundEdgeJointSolidc                  n    e Zd ZdZedd       Zedd       Z	 	 d	 	 	 	 	 d fdZedd	 	 	 dd       Z	eddd	 	 	 	 	 dd	       Z	edd
dd       Z	edddd       Z	edd       Z	d fdZ	edddd       Z
eddd	 	 	 	 	 dd       Z
edd
dd       Z
edddd       Z
edd       Z
d dZ
 xZS )!
RigidJointa]  RigidJoint

    A rigid joint fixes two components to one another.

    Args:
        label (str): joint label
        to_part (Union[Solid, Compound], optional): object to attach joint to
        joint_location (Location): global location of joint

    Attributes:
        relative_location (Location): joint location relative to bound object

    c                    | j                   j                  | j                  t        d      | j                   j                  | j                  z  S zLocation of jointzJoints are invalidparentlocationrelative_locationRuntimeErrorselfs    I/opt/ringagent/.cad-venv/lib/python3.12/site-packages/build123d/joints.pyr   zRigidJoint.locationD   F     ;;'4+A+A+I344{{##d&<&<<<    c                    | j                   j                  d      j                  dz  }t        j                  |      j                  | j                        S )z-A CAD symbol (XYZ indicator) as bound to partFoptimal   )
axes_scale)r   bounding_boxdiagonalr   
make_triadlocater   )r   sizes     r   symbolzRigidJoint.symbolK   sF     {{'''6??"D""d3::4==IIr!   Nc                8   t        j                  |       }t        ||        |||}nt        d      |}|
t	               }|j
                  t        d      |j
                  j                         |z  | _        | |j                  |<   t        | )  ||       y N2Either specify to_part or place in BuildPart scopePart must have a location)r   _get_contextr   
ValueErrorr
   r   inverser   jointssuper__init__)r   labelto_partjoint_locationcontextpart_or_builder	__class__s         r   r6   zRigidJoint.__init__Q   s     %.$:$:4$@&?"") !UVV%O!%ZN##+899!0!9!9!A!A!Cn!T(,u%0r!   anglesc                    y)z Connect RigidJoint and BallJointN )r   otherr>   kwargss       r   
connect_tozRigidJoint.connect_toj       r!   positionanglec                    y)z'Connect RigidJoint and CylindricalJointNr@   r   rA   rF   rG   s       r   rC   zRigidJoint.connect_top   rD   r!   rF   c                    y)z"Connect RigidJoint and LinearJointNr@   r   rA   rF   s      r   rC   zRigidJoint.connect_toz   rD   r!   rG   c                    y)z$Connect RigidJoint and RevoluteJointNr@   r   rA   rG   s      r   rC   zRigidJoint.connect_to~   rD   r!   c                     yz Connect two RigidJoints togetherNr@   r   rA   s     r   rC   zRigidJoint.connect_to   rD   r!   c                $    t        |   |fi |S )a  Connect the RigidJoint to another Joint

        Args:
            other (Joint): joint to connect to
            angle (float, optional): angle in degrees. Defaults to range min.
            angles (RotationLike, optional): angles about axes in degrees. Defaults to
                range minimums.
            position (float, optional): linear position. Defaults to linear range min.

        r5   _connect_tor   rA   rB   r<   s      r   rC   zRigidJoint.connect_to   s     w"53F33r!   c                    y)z RigidJoint relative to BallJointNr@   )r   rA   r>   s      r   relative_tozRigidJoint.relative_to   rD   r!   c                    y)z'RigidJoint relative to CylindricalJointNr@   rI   s       r   rX   zRigidJoint.relative_to   rD   r!   c                    y)z"RigidJoint relative to LinearJointNr@   rL   s      r   rX   zRigidJoint.relative_to   rD   r!   c                    y)z$RigidJoint relative to RevoluteJointNr@   rO   s      r   rX   zRigidJoint.relative_to   rD   r!   c                     yrQ   r@   rR   s     r   rX   zRigidJoint.relative_to   rD   r!   c                   t        |t              r)| j                  |j                  j                         z  }|S t        |t              r2d}|rd|v r|d   n|}|j                  | |      j                         }|S t        |t              r2d}|rd|v r|d   n|}|j                  | |      j                         }|S t        |t              rAd\  }}|rd|v r|d   n|}d|v r|d   n|}|j                  | ||      j                         }|S t        |t              r2d}|rd|v r|d   n|}|j                  | |	      j                         }|S t        d
t        |             )a0  Relative location of RigidJoint to another Joint

        Args:
            other (RigidJoint): relative to joint
            angle (float, optional): angle in degrees. Defaults to range min.
            angles (RotationLike, optional): angles about axes in degrees. Defaults to
                range minimums.
            position (float, optional): linear position. Defaults to linear range min.

        Raises:
            TypeError: other must be of a type in: BallJoint, CylindricalJoint,
                LinearJoint, RevoluteJoint, RigidJoint.

        NrG   rM   rF   rJ   NNrE   r>   r=   z_other must one of type BallJoint, CylindricalJoint, LinearJoint, RevoluteJoint, RigidJoint not )
isinstancer   r   r3   RevoluteJointrX   LinearJointCylindricalJoint	BallJoint	TypeErrortype)r   rA   rB   other_locationrG   rF   r>   s          r   rX   zRigidJoint.relative_to   s    eZ(!33e6M6M6U6U6WWN> = }-E+2f+<w%"..t5.AIIKN4 3 {+H1;v1E6*-8"..th.GOOQN* ) /0(OE8+2f+<w%1;v1E6*-8"..xu / gi   y)F-5-?)V"..tF.CKKMN  E{m% r!   returnr
   rh   r   r^   )r7   strr8   Solid | Compound | Noner9   Location | None)rA   rc   r>   RotationLike | None)rA   rb   rF   float | NonerG   rn   )rA   ra   rF   rn   )rA   r`   rG   rn   )rA   r   rA   r   )rA   r   rh   r
   )__name__
__module____qualname____doc__propertyr   r,   r6   r   rC   rX   __classcell__r<   s   @r   r   r   5   s    = = J J ,0*.	11 )1 (	12 AE//+>/ /
 
 "&"66 	6
 6 6 IM 1 1 HL 3 3 / /4 MQ / / 
 "&"66 	6
 6 6 JN 1 1 IM 3 3 / //r!   r   c                       e Zd ZdZed
d       Zedd       Zdej                  ddf	 	 	 	 	 	 	 	 	 d fdZ	ddd fdZ
dddd	Z xZS )r`   a)  RevoluteJoint

    Component rotates around axis like a hinge.

    Args:
        label (str): joint label
        to_part (Union[Solid, Compound], optional): object to attach joint to
        axis (Axis): axis of rotation
        angle_reference (VectorLike, optional): direction normal to axis defining where
            angles will be measured from. Defaults to None.
        range (tuple[float, float], optional): (min,max) angle of joint. Defaults to (0, 360).

    Attributes:
        angle (float): angle of joint
        angle_reference (Vector): reference for angular positions
        angular_range (tuple[float,float]): min and max angular position of joint
        relative_axis (Axis): joint axis relative to bound part

    Raises:
        ValueError: angle_reference must be normal to axis
    c                    | j                   j                  | j                  j                  t        d      | j                   j                  | j                  j                  z  S r   r   r   relative_axisr   r   s    r   r   zRevoluteJoint.location   R     ;;'4+=+=+F+F+N344{{##d&8&8&A&AAAr!   c           
     *   | j                   j                  d      j                  dz  }t        t	        j
                  ddd|dz  f      t	        j                  |      t	        j
                  d|ddf      g      j                  | j                        S )z?A CAD symbol representing the axis of rotation as bound to partFr#      r   r   r   r   
   )	r   r'   r(   r   r   	make_linemake_circlemover   r   radiuss     r   r,   zRevoluteJoint.symbol   s     ))%)8AABFy1a"*=>  (y61a.9
 $t}}
	r!   Nr   ih  c                   t        j                  |       }t        ||        |||}nt        d      |}|| _        |r7|j                  t        d|            st        d      t        |      | _        n&t        d|j                        j                  | _        d | _        |j                  t        d      |j                  |j                  j                               | _        | |j"                  |<   t$        | M  ||       y Nr/   r~   z&angle_reference must be normal to axis)originz_dirr0   )r   r1   r   r2   angular_range	is_normalr	   r   angle_referencer   	directionx_dir_angler   locatedr3   rz   r4   r5   r6   )	r   r7   r8   axisr   r   r:   r;   r<   s	           r   r6   zRevoluteJoint.__init__
  s     %.$:$:4$@&?"") !UVV%O*>>$y/"BC !IJJ#)/#:D #(	#P#V#VD $(##+899!\\/*B*B*J*J*LM(,u%0r!   rM   c               &    t         |   ||      S )a.  Connect RevoluteJoint and RigidJoint

        Args:
            other (RigidJoint): relative to joint
            angle (float, optional): angle in degrees. Defaults to range min.

        Returns:
            TypeError: other must of type RigidJoint
            ValueError: angle out of range
        rM   rT   )r   rA   rG   r<   s      r   rC   zRevoluteJoint.connect_to*  s     w"5"66r!   c                  t        |t              st        dt        |             || j                  d   n|}|| j                  d   k  s|| j                  d   kD  rt        d| d| j                         || _        |dk(  rdn|}| j                  j                  t        dd|      z  |j                  j                         z  S )a9  Relative location of RevoluteJoint to RigidJoint

        Args:
            other (RigidJoint): relative to joint
            angle (float, optional): angle in degrees. Defaults to range min.

        Raises:
            TypeError: other must of type RigidJoint
            ValueError: angle out of range
        "other must of type RigidJoint not r      angle () must in range of         g     v@)r_   r   rd   re   r   r2   r   rz   r   r   r   r3   )r   rA   rG   angle_degreess       r   rX   zRevoluteJoint.relative_to7  s     %,@eNOO16**1-ED..q11t11!44-(;D<N<N;OP  $!.#!5=''q!]+,%%--/0	
r!   rg   ri   )
r7   rj   r8   rk   r   r	   r   VectorLike | Noner   tuple[float, float])rA   r   rG   rn   )rp   rq   rr   rs   rt   r   r,   r	   Zr6   rC   rX   ru   rv   s   @r   r`   r`      s    , B B 
 
 ,0VV-1-511 )1 	1
 +1 +1@ FJ 7 GK 
 
r!   r`   c                       e Zd ZdZedd       Zedd       Zdej                  de	ff	 	 	 	 	 	 	 d fdZ
eddd	 	 	 	 	 dd       Zedd	dd
       Zd fdZedd	dd       Zeddd	 	 	 	 	 dd       Zd Z xZS )ra   aW  LinearJoint

    Component moves along a single axis.

    Args:
        label (str): joint label
        to_part (Union[Solid, Compound], optional): object to attach joint to
        axis (Axis): axis of linear motion
        range (tuple[float, float], optional): (min,max) position of joint.
            Defaults to (0, inf).

    Attributes:
        axis (Axis): joint axis
        angle (float): angle of joint
        linear_range (tuple[float,float]): min and max positional values
        position (float): joint position
        relative_axis (Axis): joint axis relative to bound part

    c                    | j                   j                  | j                  j                  t        d      | j                   j                  | j                  j                  z  S r   ry   r   s    r   r   zLinearJoint.locationl  r{   r!   c           	         | j                   d   | j                   d   z
  dz  }t        t        j                  dd| j                   d   fdd| j                   d   f      t        j                  |      g      j                  | j                        S )z;A CAD symbol of the linear axis positioned relative to_partr   r      linear_ranger   r   r   r   r   r   r   s     r   r,   zLinearJoint.symbols  s     ##A&):):1)==C4,,Q/01a9J9J19M2N   (	
 $t}}
	r!   Nr   c                p   t        j                  |       }t        ||        |||}nt        d      |}|| _        || _        d | _        |j                  t        d      |j                  |j                  j                               | _
        d | _        | |j                  |<   t        | 9  ||       y r.   )r   r1   r   r2   r   r   rF   r   r   r3   rz   rG   r4   r5   r6   )r   r7   r8   r   r   r:   r;   r<   s          r   r6   zLinearJoint.__init__  s     %.$:$:4$@&?"") !UVV%O	(##+899!\\/*B*B*J*J*LM
(,u%0r!   rE   c                    y)z%Connect LinearJoint and RevoluteJointNr@   rI   s       r   rC   zLinearJoint.connect_to  rD   r!   rJ   c                    y)z"Connect LinearJoint and RigidJointNr@   rL   s      r   rC   zLinearJoint.connect_to  rD   r!   c                $    t        |   |fi |S )a  Connect LinearJoint to another Joint

        Args:
            other (Joint): joint to connect to
            angle (float, optional): angle in degrees. Defaults to range min.
            position (float, optional): linear position. Defaults to linear range min.

        Raises:
            TypeError: other must be of type RevoluteJoint or RigidJoint
            ValueError: position out of range
            ValueError: angle out of range
        rT   rV   s      r   rC   zLinearJoint.connect_to  s     w"53F33r!   c                    y)z.Relative location of LinearJoint to RigidJointNr@   rL   s      r   rX   zLinearJoint.relative_to  rD   r!   c                    y)z1Relative location of LinearJoint to RevoluteJointNr@   rI   s       r   rX   zLinearJoint.relative_to  rD   r!   c           	        d\  }}|rd|v r|d   n|}d|v r|d   n|}t        |t        t        f      st        dt	        |             |t        | j                        dz  n|}| j                  d   |cxk  r| j                  d   k  sn t        d| d	| j                         || _        t        |t              r||j                  d   n|}|j                  d   |cxk  r|j                  d   k  sn t        d
| d	|j                         t        t        d|j                  j                  |j                  |      |j                  j                              }nd}t               }|| _        t        | j                  j                  | j                  j                  |z  z         |z  }t        |t              r t        |j                  j                        }n|j"                  }||j%                         z  S )a  Relative location of LinearJoint to RevoluteJoint or RigidJoint

        Args:
            other (Joint): joint to connect to
            angle (float, optional): angle in degrees. Defaults to range min.
            position (float, optional): linear position. Defaults to linear range min.

        Raises:
            TypeError: other must be of type RevoluteJoint or RigidJoint
            ValueError: position out of range
            ValueError: angle out of range
        r^   rF   rG   z3other must of type RigidJoint or RevoluteJoint not    r   r   
position (r   r   r~   r   r   r   r   )r_   r   r`   rd   re   sumr   r2   rF   r   r
   r   r   rotaterz   r   rG   r   r3   )r   rA   rB   rF   rG   rotationjoint_relative_positionother_relative_locations           r   rX   zLinearJoint.relative_to  s    %%-76-Avj)xH'.&'8F7OeE%*m!<=Ed5k]S  2:1A3t(()A-x  #xG43D3DQ3GGXJ&9$:K:K9LM  !e]+.3mE''*E&&q)ULe6I6I!6LL eW$78K8K7LM   $//66u7J7JER--77H EzH
""++d.@.@.J.JX.UU  	  e]+&.u/B/B/K/K&L#&+&=&=#&)@)H)H)JJJr!   rg   ri   )r7   rj   r8   rk   r   r	   r   r   )rA   r`   rF   rn   rG   rn   )rA   r   rF   rn   ro   )rp   rq   rr   rs   rt   r   r,   r	   r   r   r6   r   rC   rX   ru   rv   s   @r   ra   ra   W  s   ( B B 
 
 ,0VV-.H11 )1 	1
 *14 
 "&"44 	4
 4 4 HL 1 14 IM = = 
 "&"@@ 	@
 @ @=Kr!   ra   c                       e Zd ZdZedd       Zedd       Zdej                  dde	fdf	 	 	 	 	 	 	 	 	 	 	 d fdZ
ddd	 	 	 	 	 d fd	Zddd	 	 	 	 	 dd
Z xZS )rb   a  CylindricalJoint

    Component rotates around and moves along a single axis like a screw.

    Args:
        label (str): joint label
        to_part (Union[Solid, Compound], optional): object to attach joint to
        axis (Axis): axis of rotation and linear motion
        angle_reference (VectorLike, optional): direction normal to axis defining where
            angles will be measured from. Defaults to None.
        linear_range (tuple[float, float], optional): (min,max) position of joint.
            Defaults to (0, inf).
        angular_range (tuple[float, float], optional): (min,max) angle of joint.
            Defaults to (0, 360).

    Attributes:
        axis (Axis): joint axis
        linear_position (float): linear joint position
        rotational_position (float): revolute joint angle in degrees
        angle_reference (Vector): reference for angular positions
        angular_range (tuple[float,float]): min and max angular position of joint
        linear_range (tuple[float,float]): min and max positional values
        relative_axis (Axis): joint axis relative to bound part
        position (float): joint position
        angle (float): angle of joint

    Raises:
        ValueError: angle_reference must be normal to axis
    c                    | j                   j                  | j                  j                  t        d      | j                   j                  | j                  j                  z  S r   ry   r   s    r   r   zCylindricalJoint.location&  r{   r!   c           
     P   | j                   d   | j                   d   z
  dz  }t        t        j                  dd| j                   d   fdd| j                   d   f      t        j                  |      t        j                  d|ddf      g      j                  | j                        S )z?A CAD symbol representing the cylindrical axis as bound to partr   r   r   r~   r   r   s     r   r,   zCylindricalJoint.symbol-  s     ##A&):):1)==C4,,Q/01a9J9J19M2N   (y61a.9
 $t}}
	r!   Nr   r   c                X   t        j                  |       }t        ||        |||}nt        d      |}|| _        d | _        d | _        |r7|j                  t        d|            st        d      t        |      | _
        n&t        d|j                        j                  | _
        || _        || _        |j                   t        d      |j#                  |j                   j%                               | _        d | _        d | _        | |j,                  |<   t.        	| a  ||       y r   )r   r1   r   r2   r   linear_positionrotational_positionr   r	   r   r   r   r   r   r   r   r   r   r3   rz   rF   rG   r4   r5   r6   )
r   r7   r8   r   r   r   r   r:   r;   r<   s
            r   r6   zCylindricalJoint.__init__;  s    %.$:$:4$@&?"") !UVV%O	##' >>$y/"BC !IJJ#)/#:D #(	#P#V#VD *(##+899!\\/*B*B*J*J*LM&*#'
(,u%0r!   rE   c               (    t         |   |||      S )a  Connect CylindricalJoint and RigidJoint"

        Args:
            other (Joint): joint to connect to
            position (float, optional): linear position. Defaults to linear range min.
            angle (float, optional): angle in degrees. Defaults to range min.

        Raises:
            TypeError: other must be of type RigidJoint
            ValueError: position out of range
            ValueError: angle out of range
        rE   rT   )r   rA   rF   rG   r<   s       r   rC   zCylindricalJoint.connect_to`  s    & w"585"IIr!   c          	     4   t        |t              st        dt        |             |t	        | j
                        dz  n|}| j
                  d   |cxk  r| j
                  d   k  sn t        d| d| j
                         || _        |t	        | j                        dz  n|}| j                  d   |cxk  r| j                  d   k  sn t        d| d| j                         || _	        t        | j                  j                  | j                  j                  |z  z         }t        t        d| j                  j                  | j                  |      | j                  j                  	            }||z  |j                   j#                         z  S )
a  Relative location of CylindricalJoint to RigidJoint

        Args:
            other (Joint): joint to connect to
            position (float, optional): linear position. Defaults to linear range min.
            angle (float, optional): angle in degrees. Defaults to range min.

        Raises:
            TypeError: other must be of type RigidJoint
            ValueError: position out of range
            ValueError: angle out of range
        r   r   r   r   r   r   r   r~   r   )r_   r   rd   re   r   r   r2   rF   r   rG   r
   rz   r   r   r   r   r   r3   )r   rA   rF   rG   position_valuer   joint_rotations          r   rX   zCylindricalJoint.relative_tou  s   & %,@eNOO7?7GT../!3X  #~M9J9J19MM^,,?@Q@Q?RS  '/4}D&&'!+%!!!$F1C1CA1FFwug-@ASAS@TUVV
"*''$*<*<*F*F*WW#
 " **11$2D2DeL((22
 $n4u7N7N7V7V7XX	
r!   rg   ri   )r7   rj   r8   rk   r   r	   r   r   r   r   r   r   )rA   r   rF   rn   rG   rn   )rp   rq   rr   rs   rt   r   r,   r	   r   r   r6   rC   rX   ru   rv   s   @r   rb   rb     s    @ B B    ,0VV-1-.H-5#1#1 )#1 	#1
 +#1 *#1 +#1R "&"JJ 	J
 J2 "&".
.
 	.

 .
r!   rb   c                       e Zd ZdZed
d       Zedd       Zdddej                  f	 	 	 	 	 	 	 	 	 d fdZ	ddd fdZ
dddd	Z xZS )rc   a  BallJoint

    A component rotates around all 3 axes using a gimbal system (3 nested rotations).

    Args:
        label (str): joint label
        to_part (Union[Solid, Compound], optional): object to attach joint to
        joint_location (Location): global location of joint
        angular_range
            (tuple[ tuple[float, float], tuple[float, float], tuple[float, float] ], optional):
            X, Y, Z angle (min, max) pairs. Defaults to ((0, 360), (0, 360), (0, 360)).
        angle_reference (Plane, optional): plane relative to part defining zero degrees of
            rotation. Defaults to Plane.XY.

    Attributes:
        relative_location (Location): joint location relative to bound part
        angular_range
            (tuple[ tuple[float, float], tuple[float, float], tuple[float, float] ]):
            X, Y, Z angle (min, max) pairs.
        angle_reference (Plane): plane relative to part defining zero degrees of

    c                    | j                   j                  | j                  t        d      | j                   j                  | j                  z  S r   r   r   s    r   r   zBallJoint.location  r    r!   c                   | j                   j                  d      j                  dz  }t        j                  || j
                        }t        j                  || j
                  j                  d            }t        j                  || j
                  j                  d            }t        |||t        j                  d|dz  dt        j                  t        j                  f	      j                  |j                  d
      t        ddd      z        t        j                  d|dz  dt        j                  t        j                  f	      j                  |j                  d      t        ddd      z        t        j                  d|dz  dt        j                  t        j                  f	      j                  |j                  d
      t        ddd      z        g      j                  | j                        S )z0A CAD symbol representing joint as bound to partFr#   r}   )Z   r   r   )r   r   r   X   
singleline)aligng      ?r   r   Yg      ?r   )r   r'   r(   r   r   r   rotatedr   	make_textr   CENTERr*   location_atr   r   r   )r   r   circle_xcircle_ycircle_zs        r   r,   zBallJoint.symbol  s    ))%)8AABF##FD,@,@A##FD,@,@,H,H,TU##FD,@,@,H,H,TU""!\%,,9U&--e4xAq7IIJ""!\%,,9U&--e4xAq7IIJ""!\%,,9U&--e4xAq7IIJ
 $t}}
	r!   N)r   r   r   c                T   t        j                  |       }t        ||        |||}nt        d      |}|
t	               }|j
                  t        d      |j
                  j                         |z  | _        | |j                  |<   || _	        || _
        t        | 1  ||       y r.   )r   r1   r   r2   r
   r   r3   r   r4   r   r   r5   r6   )	r   r7   r8   r9   r   r   r:   r;   r<   s	           r   r6   zBallJoint.__init__  s     %.$:$:4$@&?"") !UVV%O!%ZN##+899!0!9!9!A!A!Cn!T(,u%*.0r!   r=   c               &    t         |   ||      S )aP  Connect BallJoint and RigidJoint

        Args:
            other (RigidJoint): joint to connect to
            angles (RotationLike, optional): angles about axes in degrees. Defaults to
                range minimums.

        Raises:
            TypeError: invalid other joint type
            ValueError: angles out of range
        r=   rT   )r   rA   r>   r<   s      r   rC   zBallJoint.connect_to  s     w"5"88r!   c                  t        |t              st        dt        |             t        |t              r|}npt        |t
              r	t	        | }nW|>t	        | j                  d   d   | j                  d   d   | j                  d   d         }nt        dt        |             || j                  j                  z  }t        g d|j                  j                  |j                  j                  |j                  j                  g      D ]M  \  }}| j                  |   d   |cxk  r| j                  |   d   k  r2n t        d| d| j                          | j                  |z  |j                  j!                         z  S )	a  relative_to - BallJoint

        Return the relative location from this joint to the RigidJoint of another object

        Args:
            other (RigidJoint): joint to connect to
            angles (RotationLike, optional): angles about axes in degrees. Defaults to
                range minimums.

        Raises:
            TypeError: invalid other joint type
            ValueError: angles out of range
        r   r   r   r   zangles is of an unknown type )r   r   r   zangles (r   )r_   r   rd   re   r   tupler   r   r   ziporientationr   r   r   r2   r   r3   )r   rA   r>   angle_rotationr   i	rotationss          r   rX   zBallJoint.relative_to
  s    %,@eNOOfh'#N&%v.N^%""1%a(""1%a(""1%a(N ;DL>JKK!D$8$8$A$AA!!##X%9%9%;%;X=Q=Q=S=ST
 	LAy %%a(+yTD<N<Nq<QRS<TT vh&9$:L:L9MN 	 %%053J3J3R3R3TTTr!   rg   ri   )
r7   rj   r8   rk   r9   rl   r   zDtuple[tuple[float, float], tuple[float, float], tuple[float, float]]r   r   )rA   r   r>   rm   )rp   rq   rr   rs   rt   r   r,   r   XYr6   rC   rX   ru   rv   s   @r   rc   rc     s    . = =  6 ,0*. +!&11 )1 (	1

1 1< NR 9 OS )U )Ur!   rc   N)rs   
__future__r   mathr   typingr   build123d.build_commonr   build123d.build_enumsr   build123d.build_partr   build123d.geometryr	   r
   r   r   r   r   r   build123d.topologyr   r   r   r   r   r`   ra   rb   rc   r@   r!   r   <module>r      s   8 #   2 ' *   < ;g gTu
E u
pkK% kK\^
u ^
BMU MUr!   