
    ,jc                     Z   d dl mZmZ d dlZddlmZ ddlmZ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 d dlmZ d dlmZmZmZmZmZ  ed	e
          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% G d de$          Z& G d de$          Z' G d de!          Z( G d de!e          Z) G d de)          Z* G d d e)          Z+ G d! d"e+          Z, G d# d$e%e+          Z- G d% d&e)          Z. G d' d(e)          Z/ G d) d*e!          Z0 G d+ d,e0          Z1 G d- d.e0          Z2 G d/ d0e0          Z3 G d1 d2e!          Z4d3 Z5 e5            Z6 G d4 d5e!          Z7d6 Z8 e8e6          Z9 G d7 d8e!          Z:dS )9    )abstractmethodABCN   )Vector)ShapeProtocolShape1DProtocolFaceProtocolgeom_LUT_EDGEgeom_LUT_FACE)
pyparsing_commonLiteralWordnumsOptionalCombineone_ofGroupinfix_notationopAssoc)reduce)IterableListSequenceTypeVarcastShape)boundc                   R    e Zd ZdZdee         dee         fdZd Zd Z	d Z
d Zd	S )
Selectorzd
    Filters a list of objects.

    Filters must provide a single method that filters objects.
    
objectListreturnc                      t          |          S )z
        Filter the provided list.

        The default implementation returns the original list unfiltered.

        :param objectList: list to filter
        :type objectList: list of OCCT primitives
        :return: filtered list
        )listselfr    s     L/DATA/AppData/hermes/venv/lib/python3.11/site-packages/cadquery/selectors.pyfilterzSelector.filter$   s     J    c                 "    t          | |          S N)AndSelectorr%   others     r&   __and__zSelector.__and__0       4'''r(   c                 "    t          | |          S r*   )SumSelectorr,   s     r&   __add__zSelector.__add__3   r/   r(   c                 "    t          | |          S r*   )SubtractSelectorr,   s     r&   __sub__zSelector.__sub__6   s    e,,,r(   c                      t          |           S r*   )InverseSelector)r%   s    r&   __neg__zSelector.__neg__9   s    t$$$r(   N)__name__
__module____qualname____doc__r   r   r   r'   r.   r2   r5   r8    r(   r&   r   r      s         
 % 
 T%[ 
  
  
  
 ( ( (( ( (- - -% % % % %r(   r   c                   0    e Zd ZdZd Zdee         fdZdS )NearestToPointSelectora  
    Selects object nearest the provided point.

    If the object is a vertex or point, the distance
    is used. For other kinds of shapes, the center of mass
    is used to to compute which is closest.

    Applicability: All Types of Shapes

    Example::

       CQ(aCube).vertices(NearestToPointSelector((0, 1, 0)))

    returns the vertex of the unit cube closest to the point x=0,y=1,z=0

    c                     || _         d S r*   )pnt)r%   rA   s     r&   __init__zNearestToPointSelector.__init__O   s    r(   r    c                 2      fd}t          ||          gS )Nc                 t    |                                                      t          j                   j        S r*   )Centersubr   rA   Length)tShaper%   s    r&   distz+NearestToPointSelector.filter.<locals>.distS   s)    ==??&&vtx'899@@r(   key)min)r%   r    rI   s   `  r&   r'   zNearestToPointSelector.filterR   s9    	A 	A 	A 	A 	A JD)))**r(   Nr9   r:   r;   r<   rB   r   r   r'   r=   r(   r&   r?   r?   =   sL         "  +% + + + + + +r(   r?   c                   2    e Zd ZdZddZdee         fdZdS )BoxSelectora^  
    Selects objects inside the 3D box defined by 2 points.

    If `boundingbox` is True only the objects that have their bounding
    box inside the given box is selected. Otherwise only center point
    of the object is tested.

    Applicability: all types of shapes

    Example::

        CQ(aCube).edges(BoxSelector((0, 1, 0), (1, 2, 1)))
    Fc                 L    t          | | _        t          | | _        || _        d S r*   )r   p0p1test_boundingbox)r%   point0point1boundingboxs       r&   rB   zBoxSelector.__init__h   s&    &/&/ +r(   r    c                   	
 g }| j                                         \  
| j                                        \  		
fd}|D ]}| j        r||                                } |t          |j        |j        |j                            r> |t          |j	        |j
        |j                            r|                    |            ||                                          r|                    |           |S )Nc                     | j         k     | j         k     z  o-| j        k     | j        k     z  o| j        k     | j        k     z  S r*   )xyz)px0x1y0y1z0z1s    r&   isInsideBoxz'BoxSelector.filter.<locals>.isInsideBoxs   sP     #(qsRx( .cBh138,.cBh138,r(   )rQ   toTuplerR   rS   BoundingBoxr   xminyminzminxmaxymaxzmaxappendrE   )r%   r    resultrc   obbr]   r^   r_   r`   ra   rb   s         @@@@@@r&   r'   zBoxSelector.filterm   s+   W__&&
BW__&&
B	 	 	 	 	 	 	 	 	 	  		% 		%A$ %]]__;vbgrw@@AA %kk27BGRW55G G % MM!$$$;qxxzz** %MM!$$$r(   N)FrM   r=   r(   r&   rO   rO   Y   sQ         , , , ,
%      r(   rO   c                   \    e Zd ZdZddedefdZdedefdZd	e	e
         dee
         fd
ZdS )BaseDirSelectorzV
    A selector that handles selection on the basis of a single direction vector.
    -C6?vector	tolerancec                 "    || _         || _        d S r*   )	directionrt   )r%   rs   rt   s      r&   rB   zBaseDirSelector.__init__   s    "r(   vecr!   c                     dS )zMTest a specified vector. Subclasses override to provide other implementationsTr=   r%   rw   s     r&   testzBaseDirSelector.test   s    tr(   r    c                    g }|D ]}|                                 dk    rA|                                dk    r)t          t          |                              d          }nY|                                 dk    r@|                                dk    r(t          t
          |                                          }n|                     |          r|                    |           |S )z
        There are lots of kinds of filters, but for planes they are always
        based on the normal of the plane, and for edges on the tangent vector
        along the edge
        FacePLANENEdgeLINE)		ShapeTypegeomTyper   r	   normalAtr   	tangentAtrz   rl   )r%   r    rrn   test_vectors        r&   r'   zBaseDirSelector.filter   s      	 	A{{}}&&1::<<7+B+B #<33<<TBB&((QZZ\\V-C-C"?A66@@BByy%% r(   N)rr   )r9   r:   r;   r<   r   floatrB   boolrz   r   r   r   r'   r=   r(   r&   rq   rq      s         # #v #% # # # # 4    % T%[      r(   rq   c                   "    e Zd ZdZdedefdZdS )ParallelDirSelectora  
    Selects objects parallel with the provided direction.

    Applicability:
        Linear Edges
        Planar Faces

    Use the string syntax shortcut \|(X|Y|Z) if you want to select based on a cardinal direction.

    Example::

        CQ(aCube).faces(ParallelDirSelector((0, 0, 1)))

    selects faces with the normal parallel to the z direction, and is equivalent to::

        CQ(aCube).faces("|Z")
    rw   r!   c                 R    | j                             |          j        | j        k     S r*   )rv   crossrG   rt   ry   s     r&   rz   zParallelDirSelector.test   s"    ~##C((/$.@@r(   Nr9   r:   r;   r<   r   r   rz   r=   r(   r&   r   r      sH         $A A4 A A A A A Ar(   r   c                   "    e Zd ZdZdedefdZdS )DirectionSelectora  
    Selects objects aligned with the provided direction.

    Applicability:
        Linear Edges
        Planar Faces

    Use the string syntax shortcut +/-(X|Y|Z) if you want to select based on a cardinal direction.

    Example::

        CQ(aCube).faces(DirectionSelector((0, 0, 1)))

    selects faces with the normal in the z direction, and is equivalent to::

        CQ(aCube).faces("+Z")
    rw   r!   c                 H    | j                             |          | j        k     S r*   )rv   getAnglert   ry   s     r&   rz   zDirectionSelector.test   s    ~&&s++dn<<r(   Nr   r=   r(   r&   r   r      s@         $= =4 = = = = = =r(   r   c                   "    e Zd ZdZdedefdZdS )PerpendicularDirSelectora  
    Selects objects perpendicular with the provided direction.

    Applicability:
        Linear Edges
        Planar Faces

    Use the string syntax shortcut #(X|Y|Z) if you want to select based on a
    cardinal direction.

    Example::

        CQ(aCube).faces(PerpendicularDirSelector((0, 0, 1)))

    selects faces with the normal perpendicular to the z direction, and is equivalent to::

        CQ(aCube).faces("#Z")
    rw   r!   c                     t          | j                            |          t          j        dz  z
            | j        k     S )N   )absrv   r   mathpirt   ry   s     r&   rz   zPerpendicularDirSelector.test   s2    4>**3//$'A+=>>OOr(   Nr   r=   r(   r&   r   r      sH         &P P4 P P P P P Pr(   r   c                   F    e Zd ZdZdefdZdee         dee         fdZ	dS )TypeSelectora  
    Selects objects having the prescribed geometry type.

    Applicability:
        Faces: PLANE, CYLINDER, CONE, SPHERE, TORUS, BEZIER, BSPLINE, REVOLUTION, EXTRUSION, OFFSET, OTHER
        Edges: LINE, CIRCLE, ELLIPSE, HYPERBOLA, PARABOLA, BEZIER, BSPLINE, OFFSET, OTHER

    You can use the string selector syntax. For example this::

        CQ(aCube).faces(TypeSelector("PLANE"))

    will select 6 faces, and is equivalent to::

        CQ(aCube).faces("%PLANE")

    
typeStringc                 8    |                                 | _        d S r*   )upperr   )r%   r   s     r&   rB   zTypeSelector.__init__  s    $**,,r(   r    r!   c                 x    g }|D ]4}|                                 | j        k    r|                    |           5|S r*   )r   r   rl   )r%   r    r   rn   s       r&   r'   zTypeSelector.filter  s@     	 	Azz||t..r(   N)
r9   r:   r;   r<   strrB   r   r   r   r'   r=   r(   r&   r   r      sc         "-3 - - - -% T%[      r(   r   c                       e Zd ZdZddededefdZdee	         d	e
e	         fd
Zede	d	efd            Zdee	         d	e
e
e	                  fdZdS )_NthSelectorzj
    An abstract class that provides the methods to select the Nth object/objects of an ordered list.
    Trr   ndirectionMaxrt   c                 0    || _         || _        || _        d S r*   )r   r   rt   )r%   r   r   rt   s       r&   rB   z_NthSelector.__init__  s    ("r(   
objectlistr!   c           	      2   t          |          dk    rt          d          |                     |          }| j        s|                                 	 || j                 }n5# t          $ r( t          d| j         dt          |                     w xY w|S )z|
        Return the nth object in the objectlist sorted by self.key and
        clustered if within self.tolerance.
        r   z/Can not return the Nth element of an empty listzAttempted to access index z of a list with length )len
ValueErrorclusterr   reverser   
IndexError)r%   r   	clusteredouts       r&   r'   z_NthSelector.filter  s     z??aNOOOLL,,	  	 	DF#CC 	 	 	\TV\\CPYNN\\  	
 
s   A" "2Bobjc                     t           )z
        Return the key for ordering. Can raise a ValueError if obj can not be
        used to create a key, which will result in obj being dropped by the
        clustering method.
        NotImplementedErrorr%   r   s     r&   rK   z_NthSelector.key3  s
     "!r(   c                    g }|D ]@}	 |                      |          }n# t          $ r Y %w xY w|                    ||f           A|                    d            g g}|d         d         }|D ]T\  }}t	          ||z
            | j        k    r|d                             |           <|                    |g           |}U|S )zS
        Clusters the elements of objectlist if they are within tolerance.
        c                     | d         S )Nr   r=   )rY   s    r&   <lambda>z&_NthSelector.cluster.<locals>.<lambda>K  s
    qt r(   rJ   r   )rK   r   rl   sortr   rt   )r%   r   key_and_objr   rK   r   starts          r&   r   z_NthSelector.cluster<  s     	+ 	+Chhsmm    Sz****^^,,,D	Aq!# 	 	HC3;4>11"$$S))))  #'''s   
++NTrr   )r9   r:   r;   r<   intr   r   rB   r   r   r   r'   r   rK   r   r=   r(   r&   r   r     s         # ## #T #U # # # #
% T%[    , "u " " " " ^"(5/ d4;6G      r(   r   c                   "    e Zd ZdZdedefdZdS )RadiusNthSelectorz
    Select the object with the Nth radius.

    Applicability:
        All Edge and Wires.

    Will ignore any shape that can not be represented as a circle or an arc of
    a circle.
    r   r!   c                     |                                 dv r't          t          |                                          S t	          d          )Nr~   Wirez%Can not get a radius from this object)r   r   r   radiusr   r   s     r&   rK   zRadiusNthSelector.keyb  sA    ==??...--44666DEEEr(   Nr9   r:   r;   r<   r   r   rK   r=   r(   r&   r   r   W  sH         Fu F F F F F F Fr(   r   c            	       J     e Zd ZdZ	 	 ddedededef fdZd	e	d
efdZ
 xZS )CenterNthSelectorz
    Sorts objects into a list with order determined by the distance of their center projected onto the specified direction.

    Applicability:
        All Shapes.
    Trr   rs   r   r   rt   c                 \    t                                          |||           || _        d S r*   )superrB   rv   )r%   rs   r   r   rt   	__class__s        r&   rB   zCenterNthSelector.__init__q  s,     	L)444r(   r   r!   c                 Z    |                                                     | j                  S r*   )rE   dotrv   r   s     r&   rK   zCenterNthSelector.key{  s     zz||///r(   r   )r9   r:   r;   r<   r   r   r   r   rB   r   rK   __classcell__r   s   @r&   r   r   i  s          "!       	 
            0u 0 0 0 0 0 0 0 0 0r(   r   c                   4     e Zd ZdZ	 ddededef fdZ xZS )	DirectionMinMaxSelectoraP  
    Selects objects closest or farthest in the specified direction.

    Applicability:
        All object types. for a vertex, its point is used. for all other kinds
        of objects, the center of mass of the object is used.

    You can use the string shortcuts >(X|Y|Z) or <(X|Y|Z) if you want to select
    based on a cardinal direction.

    For example this::

        CQ(aCube).faces(DirectionMinMaxSelector((0, 0, 1), True))

    Means to select the face having the center of mass farthest in the positive
    z direction, and is the same as::

        CQ(aCube).faces(">Z")

    Trr   rs   r   rt   c                 R    t                                          d|||           d S )Nr   )r   rs   r   rt   )r   rB   )r%   rs   r   rt   r   s       r&   rB   z DirectionMinMaxSelector.__init__  s9     	li 	 	
 	
 	
 	
 	
r(   r   )	r9   r:   r;   r<   r   r   r   rB   r   r   s   @r&   r   r     sk         , MS
 

,0
DI
 
 
 
 
 
 
 
 
 
r(   r   c            	       X    e Zd ZdZ	 	 ddedededefdZd	e	e
         d
ee
         fdZdS )DirectionNthSelectorz
    Filters for objects parallel (or normal) to the specified direction then returns the Nth one.

    Applicability:
        Linear Edges
        Planar Faces
    Trr   rs   r   r   rt   c                 x    t                               | ||           t                              | |||           d S r*   )r   rB   r   )r%   rs   r   r   rt   s        r&   rB   zDirectionNthSelector.__init__  s<     	$$T69===dA|Y?????r(   r   r!   c                 r    t                               | |          }t                              | |          }|S r*   )r   r'   r   )r%   r   s     r&   r'   zDirectionNthSelector.filter  s2    (//jAA
!((z::
r(   Nr   )r9   r:   r;   r<   r   r   r   r   rB   r   r   r   r'   r=   r(   r&   r   r     s          "!@ @@ @ 	@
 @ @ @ @% T%[      r(   r   c                   "    e Zd ZdZdedefdZdS )LengthNthSelectorzh
    Select the object(s) with the Nth length

    Applicability:
        All Edge and Wire objects
    r   r!   c                     |                                 dv r't          t          |                                          S t	          dt          |          j                   )Nr   z5LengthNthSelector supports only Edges and Wires, not )r   r   r   rG   r   typer9   r   s     r&   rK   zLengthNthSelector.key  sX    ==??...--44666\S		HZ\\  r(   Nr   r=   r(   r&   r   r     s@         u       r(   r   c                   "    e Zd ZdZdedefdZdS )AreaNthSelectora  
    Selects the object(s) with Nth area

    Applicability:
        - Faces, Shells, Solids - Shape.Area() is used to compute area
        - closed planar Wires - a temporary face is created to compute area

    Will ignore non-planar or non-closed wires.

    Among other things can be used to select one of
    the nested coplanar wires or faces.

    For example to create a fillet on a shank::

       result = (
           cq.Workplane("XY")
           .circle(5)
           .extrude(2)
           .circle(2)
           .extrude(10)
           .faces(">Z[-2]")
           .wires(AreaNthSelector(0))
           .fillet(2)
       )

    Or to create a lip on a case seam::

       result = (
           cq.Workplane("XY")
           .rect(20, 20)
           .extrude(10)
           .edges("|Z or <Z")
           .fillet(2)
           .faces(">Z")
           .shell(2)
           .faces(">Z")
           .wires(AreaNthSelector(-1))
           .toPending()
           .workplane()
           .offset2D(-1)
           .extrude(1)
           .faces(">Z[-2]")
           .wires(AreaNthSelector(0))
           .toPending()
           .workplane()
           .cutBlind(2)
       )
    r   r!   c                    |                                 dv r|                                S |                                 dk    rp	 ddlm}m} t          |                    t          ||                                                              S # t          $ r}t          d| d          d }~ww xY wt          dt          |          j                   )N)r|   ShellSolidr   r   )r|   r   z"Can not compute area of the Wire: z4. AreaNthSelector supports only closed planar Wires.zCAreaNthSelector supports only Wires, Faces, Shells and Solids, not )r   Areacadquery.occ_impl.shapesr|   r   r   makeFromWiresr   	Exceptionr   r   r9   )r%   r   r|   r   exs        r&   rK   zAreaNthSelector.key  s    ==??88888::]]__&&????????4--d4oo>>CCEEFFF    qqqq  
 jVZ[^V_V_Vhjj  s   A	B 
B0B++B0Nr   r=   r(   r&   r   r     sA        / /bu       r(   r   c                   6    e Zd ZdZd Zdee         fdZd ZdS )BinarySelectorz
    Base class for selectors that operates with two other
    selectors. Subclass must implement the :filterResults(): method.
    c                 "    || _         || _        d S r*   )leftright)r%   r   r   s      r&   rB   zBinarySelector.__init__  s    	


r(   r    c                     |                      | j                            |          | j                            |                    S r*   )filterResultsr   r'   r   r$   s     r&   r'   zBinarySelector.filter  s?    !!IZ(($**;*;J*G*G
 
 	
r(   c                     t           r*   r   r%   r_leftr_rights      r&   r   zBinarySelector.filterResults  s    !!r(   N)	r9   r:   r;   r<   rB   r   r   r'   r   r=   r(   r&   r   r     s[         
  
% 
 
 
 

" " " " "r(   r   c                       e Zd ZdZd ZdS )r+   zT
    Intersection selector. Returns objects that is selected by both selectors.
    c                 Z    t          t          |          t          |          z            S r*   r#   setr   s      r&   r   zAndSelector.filterResults$  s!    CKK#g,,.///r(   Nr9   r:   r;   r<   r   r=   r(   r&   r+   r+     s-         0 0 0 0 0r(   r+   c                       e Zd ZdZd ZdS )r1   zC
    Union selector. Returns the sum of two selectors results.
    c                 @    t          t          ||z                       S r*   r   r   s      r&   r   zSumSelector.filterResults.  s    C())***r(   Nr   r=   r(   r&   r1   r1   )  s-         + + + + +r(   r1   c                       e Zd ZdZd ZdS )r4   za
    Difference selector. Subtract results of a selector from another
    selectors results.
    c                 Z    t          t          |          t          |          z
            S r*   r   r   s      r&   r   zSubtractSelector.filterResults9  s!    CKK#g,,.///r(   Nr   r=   r(   r&   r4   r4   3  s-         
0 0 0 0 0r(   r4   c                   0    e Zd ZdZd Zdee         fdZdS )r7   z
    Inverts the selection of given selector. In other words, selects
    all objects that is not selected by given selector.
    c                     || _         d S r*   )selector)r%   r   s     r&   rB   zInverseSelector.__init__C  s     r(   r    c                 j    t          t                      | j                                      |          S r*   )r4   r   r   r'   r$   s     r&   r'   zInverseSelector.filterF  s&    

DM::AA*MMMr(   NrM   r=   r(   r&   r7   r7   =  sS         
! ! !N% N N N N N Nr(   r7   c            	         t          d          } t          d          t          d          z  }t          t                    }t          t	          |          |z             }t          |t	          | t	          |          z             z             }t          d          }t          d          }t          d          }t          | |d          z   |z    |d          z   |z    |d	          z   |z   d
          }t          g d          }	 |	d           |d          z  }
t          t          t          j                              t          t          j                              z  d          }|
                    t          j                  }t          d          }t          ddg          }t          ddg          }t          t	          d          t          t                    z             }t          d                                          }t          d                                          }| |d          z   |z   }t          g d          }t          g d          } |
d           |d           |d          z   z   |d           |
d          z   t	          |          z   z   |d            |
d          z   t	          |          z   z   |d!           |
d          z   z   |d"          z  S )#zC
    Define the simple string selector grammar using PyParsing
    .+-(),rY   rZ   r[   F)adjacent)XYZXYXZYZ
simple_dir
vector_dirT)caseless%><>><<[]index)|#r   r   frontbackr   r   topbottomonly_dirtype_opcq_typedir_opdircenter_nth_opother_op
named_view)r   r   r   r   r   r   r   r
   valuesr   set_parse_actionr   upcase_tokensr   suppress)pointplusminnumberintegerfloatnlbracketrbracketcommars   r  rv   cqtyper  direction_opr  	ix_number
lsqbracket
rsqbracketr  r  r  s                        r&   _makeGrammarr1  K  s    CLLEcllWS\\)G$ZZFhw''&011GWx0@0@(@AAABBF s||Hs||HCLLE66#;;&4u<vvc{{JXU  F 999::J
<((66,+?+??I M ""##c-*>*@*@&A&AAD  F $$%5%CDDF cllG 3*%%L D$<((M hsmmd4jj011I&&((J&&((J7+++j8E ***++H KKKLLJ 		*79y 1 11	3<!!IIe$4$44xF	H =))IIe,<,<<xN	P 8J))E"2"22		4
 *\
"
"	#r(   c                   <    e Zd ZdZd Zd Zd Zdee         fdZ	dS )_SimpleStringSyntaxSelectorzg
    This is a private class that converts a parseResults object into a simple
    selector object
    c           
      P   t          ddd          t          ddd          t          ddd          t          ddd          t          ddd          t          ddd          d| _        t          ddd          dft          ddd          dft          ddd          dft          ddd          dft          ddd          dft          ddd          dfd| _        ddddd| _        t          d t
          t          d	| _        || _        | 	                    |          | _
        d S )
Nr   r   )r   r  r  r  r  r  TFr  )r
  r  r  r  c                 "    t          |            S r*   )r   )vs    r&   r   z6_SimpleStringSyntaxSelector.__init__.<locals>.<lambda>  s    ,aR00 r(   )r   r   r  r  )r   axes
namedViewsoperatorMinMaxr   r   r   operatorparseResults_chooseSelector
mySelector)r%   r;  s     r&   rB   z$_SimpleStringSyntaxSelector.__init__  s;    1a1a1aAq//Aq//Aq//
 
	 Q1oot,Aq!__e,Aq!__e,Q1oot,1aOOT*aA.
 
 	
 
 #00)$	
 
 )..|<<r(   c           	      >   d|v r$|                      |          }t          |          S d|v rt          |j                  S d|v r|                      |          }| j        |j                 }d|v rHt          |t          d                    |j	        
                                                    |          S t          ||          S d|v r|                      |          }| j        |j                 }d|v rHt          |t          d                    |j	        
                                                    |          S t          |d|          S d|v r0|                      |          } | j        |j                 |          S | j        |j                 }t          | S )	z<
        Sets up the underlying filters accordingly
        r  r  r  r   r  r   r  )
_getVectorr   r   r  r9  r  r   r   joinr  asListr   r  r   r:  r  r8  r  )r%   prrw   minmaxargss        r&   r<  z+_SimpleStringSyntaxSelector._chooseSelector  s    //"%%C$S)))"__
+++^^//"%%C(3F"}}+RWWRX__%6%67788&   /sF;;;""//"%%C()9:F"}}(c"''"(//:K:K2L2L.M.MvVVV(b&9992//"%%C-4=-c222 ?2=1D*D11r(   c                     d|v rN|j         }t          t          |j                  t          |j                  t          |j                            S | j        |j                 S )zA
        Translate parsed vector string into a CQ Vector
        r  )r  r   r   rY   rZ   r[   r7  r  )r%   rC  rw   s      r&   r@  z&_SimpleStringSyntaxSelector._getVector  sO     2-C%,,ceeCEllCCC9R]++r(   r    c                 6    | j                             |          S )z~
        selects minimum, maximum, positive or negative values relative to a direction
        ``[+|-|<|>|] <X|Y|Z>``
        r=  r'   r$   s     r&   r'   z"_SimpleStringSyntaxSelector.filter  s    
 %%j111r(   N)
r9   r:   r;   r<   rB   r<  r@  r   r   r'   r=   r(   r&   r3  r3    sl         
$= $= $=L%2 %2 %2N, , ,2% 2 2 2 2 2 2r(   r3  c           
      b   t          d          }t          d          }t          ddg          }t          d          }d }|                     |           d }d }d	 }d
 }	t          | |dt          j        |f|dt          j        |f|dt          j        |f|dt          j        |	fg          }
|
S )zx
    Define the complex string selector grammar using PyParsing (which supports
    logical operations and nesting)
    andorexcexceptnotc                      t          |           S r*   )r3  )ress    r&   atom_callbackz-_makeExpressionGrammar.<locals>.atom_callback  s    *3///r(   c                 r    |                                  d         d d d         }t          t          |          S Nr   r   )rB  r   r+   rP  itemss     r&   and_callbackz,_makeExpressionGrammar.<locals>.and_callback  .    

Q!$k5)))r(   c                 r    |                                  d         d d d         }t          t          |          S rS  )rB  r   r1   rT  s     r&   or_callbackz+_makeExpressionGrammar.<locals>.or_callback
  rW  r(   c                 r    |                                  d         d d d         }t          t          |          S rS  )rB  r   r4   rT  s     r&   exc_callbackz,_makeExpressionGrammar.<locals>.exc_callback  s/    

Q!$&...r(   c                 `    |                                  d         d         }t          |          S )Nr   r   )rB  r7   )rP  r   s     r&   not_callbackz,_makeExpressionGrammar.<locals>.not_callback  s&    

Q"u%%%r(   r   r   )r   r   r!  r   r   LEFTRIGHT)atomand_opor_opdelta_opnot_oprQ  rV  rY  r[  r]  exprs              r&   _makeExpressionGrammarrf    s     U^^FDMMEuh'((HU^^F0 0 0 	-(((* * *
* * *
/ / /
& & &
 Ql3Aw|[1q',5Q|4		
 D Kr(   c                   0    e Zd ZdZd Zdee         fdZdS )StringSyntaxSelectoray  
    Filter lists objects using a simple string syntax. All of the filters available in the string syntax
    are also available ( usually with more functionality ) through the creation of full-fledged
    selector objects. see :py:class:`Selector` and its subclasses

    Filtering works differently depending on the type of object list being filtered.

    :param selectorString: A two-part selector string, [selector][axis]

    :return: objects that match the specified selector

    ***Modifiers*** are ``('|','+','-','<','>','%')``

        :\|:
            parallel to ( same as :py:class:`ParallelDirSelector` ). Can return multiple objects.
        :#:
            perpendicular to (same as :py:class:`PerpendicularDirSelector` )
        :+:
            positive direction (same as :py:class:`DirectionSelector` )
        :-:
            negative direction (same as :py:class:`DirectionSelector`  )
        :>:
            maximize (same as :py:class:`DirectionMinMaxSelector` with directionMax=True)
        :<:
            minimize (same as :py:class:`DirectionMinMaxSelector` with directionMax=False )
        :%:
            curve/surface type (same as :py:class:`TypeSelector`)

    ***axisStrings*** are: ``X,Y,Z,XY,YZ,XZ`` or ``(x,y,z)`` which defines an arbitrary direction

    It is possible to combine simple selectors together using logical operations.
    The following operations are supported

        :and:
            Logical AND, e.g. >X and >Y
        :or:
            Logical OR, e.g. \|X or \|Y
        :not:
            Logical NOT, e.g. not #XY
        :exc(ept):
            Set difference (equivalent to AND NOT): \|X exc >Z

    Finally, it is also possible to use even more complex expressions with nesting
    and arbitrary number of terms, e.g.

        (not >X[0] and #XY) or >XY[0]

    Selectors are a complex topic: see :ref:`selector_reference` for more information
    c                     || _         t                              |d          }|                                d         | _        dS )zl
        Feed the input string through the parser and construct an relevant complex selector object
        T)	parse_allr   N)selectorString_expression_grammarparse_stringrB  r=  )r%   rk  parse_results      r&   rB   zStringSyntaxSelector.__init__\  sA     -*77RV7WW&--//2r(   r    c                 6    | j                             |          S )z`
        Filter give object list through th already constructed complex selector object
        rH  r$   s     r&   r'   zStringSyntaxSelector.filterd  s     %%j111r(   NrM   r=   r(   r&   rh  rh  )  sM        0 0d3 3 32% 2 2 2 2 2 2r(   rh  );abcr   r   r   occ_impl.geomr   occ_impl.shape_protocolsr   r   r	   r
   r   	pyparsingr   r   r   r   r   r   r   r   r   r   	functoolsr   typingr   r   r   r   r   r   objectr   r?   rO   rq   r   r   r   r   r   r   r   r   r   r   r   r   r+   r1   r4   r7   r1  _grammarr3  rf  rl  rh  r=   r(   r&   <module>rx     ss   # # # # # # # #  ! ! ! ! ! !                                           : : : : : : : : : : : : : :}---% % % % %v % % %@+ + + + +X + + +8. . . . .( . . .b# # # # #h # # #LA A A A A/ A A A.= = = = = = = =.P P P P P P P P0    8   :A A A A A8S A A AHF F F F F F F F$0 0 0 0 0 0 0 0,
 
 
 
 
/ 
 
 
>    .0A   2       "A A A A Al A A AH" " " " "X " " "&0 0 0 0 0. 0 0 0+ + + + +. + + +0 0 0 0 0~ 0 0 0N N N N Nh N N N< < <~ <>>b2 b2 b2 b2 b2( b2 b2 b2J1 1 1h -,X66 ?2 ?2 ?2 ?2 ?28 ?2 ?2 ?2 ?2 ?2r(   