
    'jM                        U d dl mZ d dlmZmZmZmZ d dlmZm	Z	 d dl
Z
d dlZd dlmZ d dl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mZmZm Z m!Z! 	 d dl"m#Z# n# e$$ r dZ#Y nw xY wg dZ% e&ej'                  Z( e&ej)                  Z* e&ej+                  Z, e&ej-                  Z. G d	 d
e/          Z0 G d de0          Z1ej2        Z3de4d<   ej5        Z6de4d<    ej7        g e6          Z8 ej7        g e3          Z9 G d de
j:                  Z; G d de;          Z< G d de;          Z=d*dZ>dZ?dZ@dZAdZBde@feAeAfeBeBeBfe?fgZCdd d*d!ZDd+d$ZEd,d%ZF G d& d'e
j:                  ZG G d( d)eG          ZHdS )-    )annotations)IterableOptionalIteratorSequence)Self	TypeAliasN)	Matrix44UVecVec2Vec3has_clockwise_orientationBezier3PBezier4PBoundingBox2dBoundingBox)PathCommandPathElementLineToMoveToCurve3ToCurve4Tonesting)
np_support)	NumpyPath2dNumpyPoints2dNumpyPoints3dNumpyShapesExceptionEmptyShapeErrorto_qpainter_pathto_matplotlib_pathsingle_pathsorient_pathsc                      e Zd ZdS )r   N__name__
__module____qualname__     H/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/npshapes.pyr   r   9           Dr+   r   c                      e Zd ZdS )r    Nr&   r*   r+   r,   r    r    =   r-   r+   r    r	   CommandNumpyTypeVertexNumpyTypedtypec                  |    e Zd ZU dZeZded<   ddZej	        dd            Z
dd	ZddZddZddZddZddZdS )NumpyShape2dzThis is an optimization to store many 2D paths and polylines in a compact way
    without sacrificing basic functions like transformation and bounding box calculation.
    npt.NDArray[VertexNumpyType]	_verticesreturntuple[Vec2, Vec2]c                    | j         }t          |          dk    rDt          |                    d                    t          |                    d                    fS t          d          zBReturns the extents of the bounding box as tuple (extmin, extmax).r   zempty shape has no extends)r6   lenr   minmaxr    selfvs     r,   extentszNumpyShape2d.extentsN   R    Nq66A::a>>4a>>11!">???r+   r   c                    d S Nr*   r?   s    r,   clonezNumpyShape2d.cloneV       r+   c                    | j         S rD   r6   rE   s    r,   np_verticeszNumpyShape2d.np_verticesZ   
    ~r+   mr
   Nonec                j    | j         }t          |          dk    rdS |                    |d           dS )-Transforms the vertices of the shape inplace.r   N   r6   r;   transform_array_inplacer?   rL   r@   s      r,   transform_inplacezNumpyShape2d.transform_inplace]   9    Nq66Q;;F	!!!Q'''''r+   
list[Vec2]c                $    d | j         D             S )ziReturns the shape vertices as list of :class:`Vec2` 
        e.g. [Vec2(1, 2), Vec2(3, 4), ...] 
        c                ,    g | ]}t          |          S r*   r   .0r@   s     r,   
<listcomp>z)NumpyShape2d.vertices.<locals>.<listcomp>h       000AQ000r+   rI   rE   s    r,   verticeszNumpyShape2d.verticesd   s     100000r+   list[tuple[float, float]]c                $    d | j         D             S )z[Returns the shape vertices as list of 2-tuples 
        e.g. [(1, 2), (3, 4), ...]
        c                ,    g | ]}t          |          S r*   )tuplerZ   s     r,   r\   z*NumpyShape2d.to_tuples.<locals>.<listcomp>n   s    111Qa111r+   rI   rE   s    r,   	to_tupleszNumpyShape2d.to_tuplesj   s     21$.1111r+   list[list[float]]c                4    | j                                         S )zXReturns the shape vertices as list of lists 
        e.g. [[1, 2], [3, 4], ...]
        )r6   tolistrE   s    r,   to_listzNumpyShape2d.to_listp   s     ~$$&&&r+   r   c                D    t          |                                           S z)Returns the bounding box of all vertices.)r   rA   rE   s    r,   bboxzNumpyShape2d.bboxv   s    T\\^^,,,r+   N)r7   r8   r7   r   r7   r5   rL   r
   r7   rM   r7   rV   )r7   r_   )r7   rd   )r7   r   )r'   r(   r)   __doc__EMPTY_SHAPEr6   __annotations__rA   abcabstractmethodrF   rJ   rT   r^   rc   rg   rj   r*   r+   r,   r4   r4   G   s           /:I9999@ @ @ @ 	      ( ( ( (1 1 1 12 2 2 2' ' ' '- - - - - -r+   r4   c                  .    e Zd ZdZddZddZeZdd
ZdS )r   z5Represents an array of 2D points stored as a ndarray.pointsOptional[Iterable[Vec2 | Vec3]]r7   rM   c                b    |r,t          j        d |D             t                    | _        d S d S )Nc                *    g | ]}|j         |j        fS r*   xyrZ   s     r,   r\   z*NumpyPoints2d.__init__.<locals>.<listcomp>   s     ,,,!#qs,,,r+   r1   nparrayr0   r6   r?   ru   s     r,   __init__zNumpyPoints2d.__init__~   sC     	X,,V,,,O  DNNN	 	r+   r   c                l    |                      d           }| j                                        |_        |S rD   	__class__r6   copyr?   rF   s     r,   rF   zNumpyPoints2d.clone   -    t$$.--//r+   intc                *    t          | j                  S rD   r;   r6   rE   s    r,   __len__zNumpyPoints2d.__len__       4>"""r+   N)ru   rv   r7   rM   rk   r7   r   r'   r(   r)   ro   r   rF   __copy__r   r*   r+   r,   r   r   {   ]        ??      
 H# # # # # #r+   r   c                  X   e Zd ZU dZded<   d3dZd4d
Zed5d            Zed5d            Z	d6dZ
d7dZeZd8dZd9dZd:dZe	 d;d<d            Zed=d            Zed=d            Zed=d             Zed=d!            Zd>d#Zd=d$Zd7d%Zd7d&Zd7d'Zd?d@d-ZdAd0ZedBd1            Zd2S )Cr   ab  Represents a 2D path, the path control vertices and commands are stored as ndarray.

    This class cannot build paths from scratch and is therefore not a drop-in replacement
    for the :class:`ezdxf.path.Path` class. Operations like transform and reverse are
    done inplace to utilize the `numpy` capabilities. This behavior is different from the
    :class:`ezdxf.path.Path` class!!!

    Construct new paths by the :class:`Path` class and convert them to
    :class:`NumpyPath2d` instances::

        path = Path((0, 0))
        path.line_to((50, 70))
        ...
        path2d = NumpyPath2d(path)

    znpt.NDArray[CommandNumpyType]	_commandspathOptional[Path]r7   rM   c                   |t           | _        t          | _        d S d |                                D             }t          |          dk    r)	 t          |j                  g}n# t          $ r g }Y nw xY wt          j
        |t                    | _        t          j
        |                                t                    | _        d S )Nc                *    g | ]}|j         |j        fS r*   ry   rZ   s     r,   r\   z(NumpyPath2d.__init__.<locals>.<listcomp>   s     @@@1QS!#J@@@r+   r   r1   )rp   r6   NO_COMMANDSr   control_verticesr;   r   start
IndexErrorr}   r~   r0   command_codesr/   )r?   r   r^   s      r,   r   zNumpyPath2d.__init__   s    <(DN(DNF@@(=(=(?(?@@@x==A ,,-   (/BBB$"4"4"6"6>NOOOs   A% %A43A4r   c                *    t          | j                  S rD   )r;   r   rE   s    r,   r   zNumpyPath2d.__len__   r   r+   r   c                6    t          | j        d                   S )z>Returns the start point as :class:`~ezdxf.math.Vec2` instance.r   r   r6   rE   s    r,   r   zNumpyPath2d.start   s     DN1%&&&r+   c                6    t          | j        d                   S )z<Returns the end point as :class:`~ezdxf.math.Vec2` instance.r   rE   s    r,   endzNumpyPath2d.end   s     DN2&'''r+   rV   c                $    d | j         D             S )Nc                ,    g | ]}t          |          S r*   rY   rZ   s     r,   r\   z0NumpyPath2d.control_vertices.<locals>.<listcomp>   r]   r+   rI   rE   s    r,   r   zNumpyPath2d.control_vertices   s    000000r+   r   c                    |                      d           }| j                                        |_        | j                                        |_        |S rD   )r   r   r   r6   r   s     r,   rF   zNumpyPath2d.clone   sB    t$$.--//.--//r+   	list[int]c                *    t          | j                  S )zInternal API.)listr   rE   s    r,   r   zNumpyPath2d.command_codes   s    DN###r+   Iterator[PathElement]c              #    K   |                                  }d}| j        D ]}|t          k    rt          ||                   V  |dz  }*|t          k    r't          ||dz            ||                   V  |dz  }\|t          k    r1t          ||dz            ||         ||dz                      V  |dz  }|t          k    rt          ||                   V  |dz  }d S )N   rP      )
r^   r   CMD_LINE_TOr   CMD_CURVE3_TOr   CMD_CURVE4_TOr   CMD_MOVE_TOr   )r?   r^   indexcmds       r,   commandszNumpyPath2d.commands   s     ==??> 	 	Ck!!Xe_-----
%%x	2HUODDDDD
%%UQY'%(519:M     
##Xe_-----
	 	r+   r   c                p    d | j         D             }d | j        D             }t          j        ||          S )z0Returns a new :class:`ezdxf.path.Path` instance.c                ,    g | ]}t          |          S r*   r   rZ   s     r,   r\   z'NumpyPath2d.to_path.<locals>.<listcomp>   s    444DGG444r+   c                ,    g | ]}t          |          S r*   )r   )r[   cs     r,   r\   z'NumpyPath2d.to_path.<locals>.<listcomp>   s    7771GAJJ777r+   )r6   r   r   from_vertices_and_commands)r?   r^   r   s      r,   to_pathzNumpyPath2d.to_path   s?    44T^44477777.xBBBr+   Fr^   Iterable[Vec2 | Vec3]closeboolc                    | d           }t          |          }t          |          dk    r|S |r<|d                             |d                   s|                    |d                    d |D             }t	          j        |t                    |_        t	          j        t          |          dz
  t          t                    |_        |S )Nr   r   c                *    g | ]}|j         |j        fS r*   ry   rZ   s     r,   r\   z-NumpyPath2d.from_vertices.<locals>.<listcomp>   s     ///13*///r+   r1   r   )
fill_valuer2   )r   r;   iscloseappendr}   r~   r0   r6   fullr   r/   r   )clsr^   r   new_pathru   s        r,   from_verticeszNumpyPath2d.from_vertices   s     3t99>>x==AO 	)!,,Xb\:: 	)OOHQK(((//h///XfODDDWKK!O;K
 
 
 r+   c                    t           | j        v S )zoReturns ``True`` if the path is a :term:`Multi-Path` object that
        contains multiple sub-paths.

        )r   r   rE   s    r,   has_sub_pathszNumpyPath2d.has_sub_paths   s     dn,,r+   c                t    t          | j                  dk    r| j                            | j                  S dS )z>Returns ``True`` if the start point is close to the end point.r   F)r;   r6   r   r   r   rE   s    r,   	is_closedzNumpyPath2d.is_closed  s6     t~"":%%dh///ur+   c                    t           | j        v S )z3Returns ``True`` if the path has any line segments.)r   r   rE   s    r,   	has_lineszNumpyPath2d.has_lines  s     dn,,r+   c                :    t           | j        v pt          | j        v S )z4Returns ``True`` if the path has any curve segments.)r   r   r   rE   s    r,   
has_curveszNumpyPath2d.has_curves  s     .Q-4>2QQr+   
list[Self]c           	        	 d	 	fd} j         t                    dk    rg S t          vr gS g  j        d	dddD ][}|t          k    rdz  nC|t
          k    rdz  n2|t          k    rdz  n!|t          k    r |             dz  	dz   dz  \d         t          k    r
 |             S )
zYield all sub-paths as :term:`Single-Path` objects.

        It's safe to call :meth:`sub_paths` on any path-type:
        :term:`Single-Path`, :term:`Multi-Path` and :term:`Empty-Path`.

        r7   rM   c                                          d           } dz            | _                 | _                            |            d S )Nr   )r   r6   r   r   )	s	cmd_indexcmd_start_indexr   r?   	sub_pathsr^   	vtx_indexvtx_start_indexs	    r,   append_sub_pathz.NumpyPath2d.sub_paths.<locals>.append_sub_path  sT    nnT**A"?Y]#BCAK"?9#<=AKQr+   r   r   rP   r   r   )r7   rM   )r   r;   r   r6   r   r   r   )
r?   r   r   r   r   r   r   r^   r   r   s
   `  @@@@@@@r,   r   zNumpyPath2d.sub_paths  sK   	  	  	  	  	  	  	  	  	  	  	  	  	  >x==AIh&&6M "	>		 	 	Ck!!Q		%%Q		%%Q		##!!!Q	"+"+a-NIIB<;&&Or+   c                    | j         rt          d          t          !t          |                                           S t          j        | j                  S )zReturns ``True`` if 2D path has clockwise orientation.

        Raises:
            TypeError: can't detect orientation of a :term:`Multi-Path` object

        z/can't detect orientation of a multi-path object)r   	TypeErrorr   r   r^   r6   rE   s    r,   r   z%NumpyPath2d.has_clockwise_orientation?  sN      	OMNNN,T]]__===7GGGr+   c                   | j         }t          | j                   s| S |d         t          k    rpt          j        |dd                                                   | _         t          j        | j        dddf         d                                          | _        n]t          j        |                                          | _         t          j        | j        d                                          | _        | S )z!Reverse path orientation inplace.r   N.r   axis)r   r;   r   r}   flipr   r6   )r?   r   s     r,   reversezNumpyPath2d.reverseM  s    >4>"" 	KB<;&&
  WXcrc]3388::DNWT^CRCH%=AFFFKKMMDNNWX..3355DNWT^!<<<AACCDNr+   c                V    |                                  s|                                  | S )zApply clockwise orientation inplace.

        Raises:
            TypeError: can't detect orientation of a :term:`Multi-Path` object

        r   r   rE   s    r,   	clockwisezNumpyPath2d.clockwise^  s*     --// 	LLNNNr+   c                V    |                                  r|                                  | S )zApply counter-clockwise orientation inplace.

        Raises:
            TypeError: can't detect orientation of a :term:`Multi-Path` object

        r   rE   s    r,   counter_clockwisezNumpyPath2d.counter_clockwisei  s*     ))++ 	LLNNNr+      distancefloatsegmentsIterator[Vec2]c           	   #    K   t          | j                  sdS |                                 }|d         }|V  d}| j        D ]!}|t          k    s|t          k    r||         }|dz  }|V  n|t
          k    re|||dz            \  }}|dz  }t          j        t          |||f          	                    ||                    }	t          |	           |	E d{V  n|t          k    rg|||dz            \  }
}}|dz  }t          j        t          ||
||f          	                    ||                    }	t          |	           |	E d{V  nt          d|           |}#dS )z4Flatten path to vertices as :class:`Vec2` instances.Nr   r   rP   r   zInvalid command: )r;   r   r^   r   r   r   r   generater   
flatteningnextr   r   
ValueError)r?   r   r   r^   r   r   r   end_locationctrlptsctrl1ctrl2s               r,   r   zNumpyPath2d.flatteningu  s     4>"" 	F==??> 	! 	!Ck!!SK%7%7'
"""""%%%-eeai.?%@"l
meT<899DDXxXX  S			%%-5eeai6G-H*ul
meUE<@AALL (  
 S			 !:S!:!:;;; EE3	! 	!r+   pathsSequence[NumpyPath2d]c                   t          |          sdS t          | j                  s|d         }|dd         }n| }|j        g}|j        g}|j        }|D ]}t          |j                  dk    r|                    |j                  sO|                    t          j        t          ft                               |                    |j                   n"|                    |j        dd                    |j        }|                    |j                   t          j        |d          | _        t          j        |          | _        dS )zExtend an existing path by appending additional paths. The paths are
        connected by MOVE_TO commands if the end- and start point of sequential paths
        are not coincident (multi-path).
        Nr   r   r1   r   )r;   r   r6   r   r   r   r   r}   r~   r   r/   concatenate)r?   r   firstr^   r   r   	next_paths          r,   extendzNumpyPath2d.extend  sC   
 5zz 	F4>"" 	!HE!""IEEE&+o%6&+o%6I 		1 		1I9&''1,,;;y// 9+?O P P PQQQ	 34444	 3ABB 7888-COOI/0000q99911r+   c                    | st          d          S | d                                         }|                    | dd                    |S )zReturns a new path of concatenated paths. The paths are connected by
        MOVE_TO commands if the end- and start point of sequential paths are not
        coincident (multi-path).
        Nr   r   )r   rF   r   )r   r   s     r,   r   zNumpyPath2d.concatenate  sL      	%t$$$a  U122Yr+   N)r   r   r7   rM   r   )r7   r   rn   rk   )r7   r   )r7   r   )r7   r   )F)r^   r   r   r   r7   r   )r7   r   )r7   r   )r   )r   r   r   r   r7   r   )r   r   r7   rM   )r   r   r7   r   )r'   r(   r)   ro   rq   r   r   propertyr   r   r   rF   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r*   r+   r,   r   r      sl         " -,,,P P P P# # # # ' ' ' X' ( ( ( X(1 1 1 1    H$ $ $ $   &C C C C <A    [" - - - X-    X - - - X- R R R XR+ + + +ZH H H H   "	 	 	 	
 
 
 
"! "! "! "! "!T2 2 2 2< 
 
 
 \
 
 
r+   r   r   Iterable[NumpyPath2d]c           	        ddl m}m t          |           } t	          |           dk    rt          d           |            }| D ]$}fd|                                D             }|                    |d                    d}|                                D ]}|t          k    r!|
                    ||                    |dz  }.|t          k    r+|                    ||         ||dz                       |dz  }d|t          k    r5|                    ||         ||dz            ||dz                       |dz  }|t          k    r |                    ||                    |dz  }А&|S )z>Convert the given `paths` into a single :class:`QPainterPath`.r   )QPainterPathQPointFone or more paths requiredc                <    g | ]} |j         |j                  S r*   ry   )r[   r@   r   s     r,   r\   z$to_qpainter_path.<locals>.<listcomp>  s)    ===''!#qs##===r+   r   rP   r   )ezdxf.addons.xqtr   r   r   r;   r   r^   moveTor   r   lineTor   quadTor   cubicTor   )r   r   qpathr   ru   r   r   r   s          @r,   r!   r!     s   66666666KKE
5zzQ5666LNNE  ====T]]__===VAY%%'' 	 	Ck!!VE]+++
%%VE]F519,=>>>
%%fUmVEAI->uqy@QRRR
##VE]+++
	 Lr+   r   rP   r   r   )r   F)detect_holesc               x   ddl m} t          |           } t          |           dk    rt	          d          |rt          |           } g }g }| D ]z}|                    |                                           |                    t                     |	                                D ]"}|
                    t          |                    #{t          j        |          }	  |||          S # t          $ rD}t	          dt          |           dt          |           dt          |                     d}~ww xY w)a  Convert the given `paths` into a single :class:`matplotlib.path.Path`.

    Matplotlib requires counter-clockwise oriented outside paths and clockwise oriented
    holes. Set the `detect_holes` argument to ``True`` if this path orientation is not
    yet satisfied.
    r   )r   r  zmatplotlib.path.Path(z, z): N)matplotlib.pathr   r   r;   r   r$   r   rJ   
MPL_MOVETOr   r   	MPL_CODESr}   r   	Exceptionstr)	r   r	  r   r^   codesr   r   ru   es	            r,   r"   r"     sZ    %$$$$$KKE
5zzQ5666 $U##!#HE ) )((**+++Z   %%'' 	) 	)CLL3((((	)^H%%FYtFE""" Y Y YWVWWE

WWsSTvvWWXXXYs   C+ +
D95?D44D9r7   list[NumpyPath2d]c                j    g }| D ]-}|                                 }|r|                    |           .|S rD   )r   r   )r   single_paths_pr   s       r,   r#   r#     sF    ')M , ,KKMM	 	,  +++r+   c                   t          |           }t          |          dk     r| S t          j        |          }t          j        |          \  }}|D ]}|                                 |D ]}|                                 ||z   S )zoReturns a new list of paths, with outer paths oriented counter-clockwise and
    holes oriented clockwise.
    rP   )r#   r;   r   make_polygon_structurewinding_deconstructionr   r   )r   r   polygonsouter_pathsholesr   s         r,   r$   r$     s     $0#6#6I
9~~-i88H !7AAK  ! !      r+   c                  l    e Zd ZU dZeZded<   ddZej	        dd            Z
dd	ZddZddZddZdS )NumpyShape3dzThis is an optimization to store many 3D paths and polylines in a compact way
    without sacrificing basic functions like transformation and bounding box calculation.
    r5   r6   r7   tuple[Vec3, Vec3]c                    | j         }t          |          dk    rDt          |                    d                    t          |                    d                    fS t          d          r:   )r6   r;   r   r<   r=   r    r>   s     r,   rA   zNumpyShape3d.extents;  rB   r+   r   c                    d S rD   r*   rE   s    r,   rF   zNumpyShape3d.cloneC  rG   r+   c                    | j         S rD   rI   rE   s    r,   rJ   zNumpyShape3d.np_verticesG  rK   r+   rL   r
   rM   c                j    | j         }t          |          dk    rdS |                    |d           dS )rO   r   Nr   rQ   rS   s      r,   rT   zNumpyShape3d.transform_inplaceJ  rU   r+   
list[Vec3]c                $    d | j         D             S )z4Returns the shape vertices as list of :class:`Vec3`.c                ,    g | ]}t          |          S r*   r   rZ   s     r,   r\   z)NumpyShape3d.vertices.<locals>.<listcomp>S  r]   r+   rI   rE   s    r,   r^   zNumpyShape3d.verticesQ  s    000000r+   r   c                D    t          |                                           S ri   )r   rA   rE   s    r,   rj   zNumpyShape3d.bboxU  s    4<<>>***r+   N)r7   r  rk   rl   rm   )r7   r#  )r7   r   )r'   r(   r)   ro   rp   r6   rq   rA   rr   rs   rF   rJ   rT   r^   rj   r*   r+   r,   r  r  4  s           /:I9999@ @ @ @ 	      ( ( ( (1 1 1 1+ + + + + +r+   r  c                  .    e Zd ZdZddZddZeZdd
ZdS )r   z5Represents an array of 3D points stored as a ndarray.ru   Optional[Iterable[UVec]]r7   rM   c                b    |r,t          j        d |D             t                    | _        d S d S )Nc                6    g | ]}t          |          j        S r*   )r   xyzrZ   s     r,   r\   z*NumpyPoints3d.__init__.<locals>.<listcomp>`  s     ---a---r+   r1   r|   r   s     r,   r   zNumpyPoints3d.__init__]  sC     	X--f---_  DNNN	 	r+   r   c                l    |                      d           }| j                                        |_        |S rD   r   r   s     r,   rF   zNumpyPoints3d.clonec  r   r+   r   c                *    t          | j                  S rD   r   rE   s    r,   r   zNumpyPoints3d.__len__j  r   r+   N)ru   r(  r7   rM   rk   r   r   r*   r+   r,   r   r   Z  r   r+   r   )r   r   )r   r   r7   r  )r   r  r7   r  )I
__future__r   typingr   r   r   r   typing_extensionsr   r	   rr   numpyr}   numpy.typingnpt
ezdxf.mathr
   r   r   r   r   r   r   r   r   
ezdxf.pathr   r   r   r   r   r   r   r   	ezdxf.accr   ImportError__all__r   MOVE_TOr   LINE_TOr   	CURVE3_TOr   	CURVE4_TOr   r  r   r    int8r/   rq   float64r0   r~   rp   r   ABCr4   r   r   r!   r  
MPL_LINETO
MPL_CURVE3
MPL_CURVE4r  r"   r#   r$   r  r   r*   r+   r,   <module>rC     s#   # " " " " " " 9 9 9 9 9 9 9 9 9 9 9 9 - - - - - - - - 



          
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	$$$$$$$   JJJ
 
 
 c'/""c'/""G%&&G%&&	 	 	 	 	9 	 	 		 	 	 	 	* 	 	 	 !g  % % % %Z ' ' ' 'bhr111bhr!12221- 1- 1- 1- 1-37 1- 1- 1-h# # # # #L # # #(y y y y y, y y yx	   < 



 	MZ(M	 FK Y Y Y Y Y Y>      *#+ #+ #+ #+ #+37 #+ #+ #+L# # # # #L # # # # #s   A A&%A&