
    hiP                        d dl Z d dlZ e j                    dk    r
dej        d<   d dlmZmZmZ d dlm	Z	 d dl
mZ d dlmZmZ d dlZd d	lmZ d d
lmZ d dlmZ d dlmZmZ ddlmZ ddlmZ e	 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#	 	 dId ed!ed"ed#ed$ed%ed&e$d'e%d(eeef         fd)Z&d*ed(ee         fd+Z'	 	 dJd ed.ed/e(d0e$fd1Z)	 	 	 	 	 	 dKd/e(d7ed!ed ed.ed8e$d9e$d:e(d;e(d<e$d=e*fd>Z+d ed.ed(ee(ef         fd?Z,d ed.ed@edAe(dBe(d(efdCZ-dLdAe(dEe(dFe(dGe$d(ef
dHZ.dS )M    NLinuxeglPYOPENGL_PLATFORM)DictListTuple)	dataclass)defaultdict)ABCabstractmethod)ndarray)cKDTree)
csr_matrix)shortest_pathconnected_components   )Asset)
ConfigSpecc                   \    e Zd ZU dZee         ed<   eeef         ed<   edd            Z	dS )VertexGroupConfigz(
    Config to sample vertex group.
    nameskwargsreturnc                     |                      |           t          |                    dg           |                    di                     S )Nr   r   )r   r   )
check_keysr   get)clsconfigs     7/data/cameron/tmprepos/2unirig/src/data/vertex_group.pyparsezVertexGroupConfig.parse    sM    v **Wb))::h++
 
 
 	
    N)r   r   )
__name__
__module____qualname____doc__r   str__annotations__r   classmethodr     r!   r   r   r      sf          
 9 dO
 
 
 [
 
 
r!   r   c                   T    e Zd Zed             Zededeeef         fd            Z	dS )VertexGroupc                     d S Nr)   selfr   s     r   __init__zVertexGroup.__init__*       r!   assetr   c                     d S r-   r)   r/   r2   s     r   get_vertex_groupzVertexGroup.get_vertex_group.   r1   r!   N)
r"   r#   r$   r   r0   r   r   r&   r   r5   r)   r!   r   r+   r+   (   sd          ^ e S'\0B    ^  r!   r+   c                   8    e Zd ZdZd Zdedeeef         fdZ	dS )VertexGroupSkinz
    Capture skin.
    c                     d S r-   r)   r.   s     r   r0   zVertexGroupSkin.__init__7       r!   r2   r   c                 T    d|j         |j                             dd          dz   z  iS )NskinTaxiskeepdimsư>)r;   sumr4   s     r   r5   z VertexGroupSkin.get_vertex_group:   s/    EJ%*..b4."H"H4"OP
 	
r!   N
r"   r#   r$   r%   r0   r   r   r&   r   r5   r)   r!   r   r7   r7   2   sX           
e 
S'\0B 
 
 
 
 
 
r!   r7   c                   x    e Zd ZdZd Zdedeeeef                  deeef         fdZ	de
deeef         fdZd	S )
VertexGroupGeodesicDistancez&
    Calculate geodesic distance.
    c                 r    |                     dd          | _        |                     dd          | _        d S )NdeterministicF	soft_mask)r   rF   rG   r.   s     r   r0   z$VertexGroupGeodesicDistance.__init__C   s1    #ZZ??K77r!   jointsedgesr   c           	         |j         d         }t          j        ||f          dz  }t          j        ||f          dz  }dt          dt          fd}t	          |          D ]}d|||f<   d|||f<   |D ]} |||d                  ||d                            ||d         |d         f<    |||d                  ||d                            ||d         |d         f<   d||d         |d         f<   d||d         |d         f<   t	          |          D ]}	t          j        ||d d |	f         d d t          j        f         ||	d d f         t          j        d d f         z             }t          j        ||d d |	f         d d t          j        f         ||	d d f         t          j        d d f         z             }||fS )Nr   g      Y@xyc                 F    t           j                            | |z
            S r-   )nplinalgnorm)rK   rL   s     r   disz1VertexGroupGeodesicDistance._prepare.<locals>.disO   s    9>>!A#&&&r!           r   )shaperN   onesr   rangeminimumnewaxis)
r/   rH   rI   J
dis_matrixstep_matrixrQ   iedgeks
             r   _preparez$VertexGroupGeodesicDistance._prepareG   s   
 LOWaV__u,
gq!foo-	'7 	'w 	' 	' 	' 	'q 	# 	#A!Jq!t "K1 	. 	.D+.3vd1gtAw+P+PJtAwQ'(+.3vd1gtAw+P+PJtAwQ'(,-KQa(),-KQa())q 	w 	wAJ
111a40@BJ0OR\]^`a`a`a]aRbcecmopopopcpRq0qrrJ*[+aaad2CAAArzM2RU`abdededeaeUfgigqstststgtUu2uvvKK;&&r!   r2   c           	         t          t                    }g }t          |j                  D ]9\  }}|2|                    ||f           ||                             |           :g }|j                                        }t          |j                  D ]i}t          ||                   dk    r"|                    ||         d                    =|                    |           | j
        r|j        |         ||<   jt          j        |          }|                     |j        |          \  }}	t          |j        |j        |||	|| j                  \  }
}|
|dS )Nr   r   )rH   rI   )verticesrH   tailsrY   rZ   childrG   )geodesic_distancegeodesic_mask)r
   list	enumerateparentsappendra   copyrU   rX   lenrF   rH   rN   arrayr^   get_geodesic_distancer`   rG   )r/   r2   childrenrI   idprb   ra   rY   rZ   geo_disgeo_masks               r   r5   z,VertexGroupGeodesicDistance.get_vertex_group_   su   t$$ // 	' 	'GR}b!W%%%""2&&&  "".. 	1 	1B8B<  A%%Xb\!_----R   % 1 %R 0E"I"&--< #0 #
 #

K 2^<!#n
 
 
 ")%
 
 	
r!   N)r"   r#   r$   r%   r0   r   r   r   intr^   r   r   r&   r5   r)   r!   r   rD   rD   ?   s         8 8 8'' E#s(O$' 
w	 	' ' ' '0!
e !
S'\0B !
 !
 !
 !
 !
 !
r!   rD   c                   8    e Zd ZdZd Zdedeeef         fdZ	dS )VertexGroupVoxelSkinz
    Capture voxel skin.
    c                    |                     dd          | _        |                     dd          | _        |                     dd          | _        |                     dd          | _        |                     d	d          | _        |                     d
d          | _        |                     dd          | _        d S )Ngrid@   alpha      ?link_dish㈵>
grid_query   vertex_querygrid_weight      @modesquare)r   rv   rx   rz   r|   r~   r   r   r.   s     r   r0   zVertexGroupVoxelSkin.__init__   s    JJvr**	ZZ--


:w77 **\266"JJ~r::!::mS99JJvx00			r!   r2   r   c                    t          j        |j        d          }t          j        |j        d          }||z   dz  }t          j        ||z
            dz  }|j        |z
  |z  }|j        |z
  |z  }t          ||j        | j                  \  }}	t          | j        |	|||j        | j	        | j
        | j        | j        | j        | j                  }
t          j        |
ddd          }
d|
iS )	Nr   r>      )r`   facesrv   )rv   grid_coordsrH   r`   r   rx   rz   r|   r~   r   r   rR   nanposinfneginf
voxel_skin)rN   minr`   maxrH   voxelizationr   rv   r   rx   rz   r|   r~   r   r   
nan_to_num)r/   r2   min_valsmax_valscenterscalenormalized_verticesnormalized_jointsgrid_indicesr   r;   s              r   r5   z%VertexGroupVoxelSkin.get_vertex_group   s    6%.q1116%.q111X%*x(*++a/$~6%?"\F2e;$0(+%
 %
 %
!k
 #$(+*]*(
 
 
 }Tr"R@@@$
 	
r!   NrB   r)   r!   r   rt   rt      sX         1 1 1"
e "
S'\0B "
 "
 "
 "
 "
 "
r!   rt   c                   4    e Zd Zd Zdedeeef         fdZdS )VertexGroupMeshPartDistancec                 :    |d         | _         |d         | _        d S )Npart_dimdis_dim)r   r   r.   s     r   r0   z$VertexGroupMeshPartDistance.__init__   s    z*i(r!   r2   r   c                 Z   t          |j        |j                  \  }}}t          |j        |j        ||| j                  }t          || j                  }t          j        |j        j	        d         | j        f          }t          |          D ]}||         |t          |k    <   |||dS )Nr   )	num_partspart_vectorspart_distances)find_connected_componentsr`   r   compute_distances_in_componentsr   generate_spread_vectorsr   rN   zerosrS   rU   labels)r/   r2   totvertex_labelsface_labelsr   r   r[   s           r   r5   z,VertexGroupMeshPartDistance.get_vertex_group   s    *CENTYT_*`*`']K8Vcehjnjvww.sDMBBx!5a!8$- HIIs 	8 	8A(4QL1%%(,
 
 	
r!   N	r"   r#   r$   r0   r   r   r&   r   r5   r)   r!   r   r   r      sN        ) ) )
e 
S'\0B 
 
 
 
 
 
r!   r   c                   4    e Zd Zd Zdedeeef         fdZdS )VertexGroupMeshPartsc                     d S r-   r)   r.   s     r   r0   zVertexGroupMeshParts.__init__   r9   r!   r2   r   c                 ~    t          |j        |j                  \  }}}||j        d<   ||j        d<   ||j        d<   i S )Nr   r   r   )r   r`   r   meta)r/   r2   r   r   r   s        r   r5   z%VertexGroupMeshParts.get_vertex_group   sG    *CENTYT_*`*`']K"%
;&3
?#$/
=!	r!   Nr   r)   r!   r   r   r      sN          e S'\0B      r!   r   -C6?Fr`   rH   ra   rY   rZ   rb   epsrG   r   c                 R   ||z
  }d||z  |z                        d          z  t          j        df         }	|t          j        df         | d d t          j        d d f         z
  }
|
|t          j        df         z                       d          |	z  }| d d t          j        d d f         |t          j        df         z
  }||t          j        df         z                       d          |	z  }t          j        |dd          |z   t          j        |dd          t          j        |dd          z   |dz  z   z  }| dz   }|dt          j        f         |t          j        df         z  |dt          j        f         |t          j        df         z  z   }t          j                            | d d t          j        d d f         |z
  d          }t          j        |d          }t          j        |j        d                   }||         ||d d t          j        f         |d d t          j        f         f         z  |||                  ||d d t          j        f         |d d t          j        f         f         z  z   }|rd||         ||d d t          j        f         |d d t          j        f         f         z  |||                  ||d d t          j        f         |d d t          j        f         f         z  z   z
                      dd          	                    t          j
                  }n||         ||d d t          j        f         |d d t          j        f         f         z  |||                  ||d d t          j        f         |d d t          j        f         f         z  z   dk    	                    t          j
                  }t          j        |dd	
          }t          j        |dd	
          }||z
  ||z
  z  }t          j        |ddd          }||fS )N      ?r<   r   .rR   r   r   r   Tr=   r   )rA   rN   rW   cliprO   rP   argminarangerS   astypefloat32r   r   r   )r`   rH   ra   rY   rZ   rb   r   rG   offsetinvg0c0g1c1scale0scale1nearestrQ   indexrresmaskrow_minrow_maxs                           r   rl   rl      s    V^Fv$))r)222BJO
DC	rz3	(111bj!!!+;"<	<B
vbj#o&
&	+	+	+	4	4s	:B	!!!RZ"	#fRZ_&=	=B
vbj#o&
&	+	+	+	4	4s	:Bgb"b!!C'BGBB,?,?"'"bRTBUBU,UX[^_X_,_`FWq[FS"*_%rz3(??&bjBY\abdblnqbq\rBrrG
)..!!!RZ"23g=B.
G
GCIc"""E
	#)A,A 	5F1QQQ
]#3U111bj=5I#IJJ5< 6!AAArzM*:E!!!RZ-<P*P#QQ	R   	$!!!RZ-(8%2::N(N!OOe%qBJ/?qqq"*}AU/U(VVW
 4B<<rz** 	 !!!RZ-(8%2::N(N!OOe%qBJ/?qqq"*}AU/U(VVW 
## 	 fSq4000GfSq4000G=Ww.
/C
-Br
:
:
:C9r!   r   c                 F   g }t           t          t          t          t          d}| j        D ]u}||v s5J dd                    |                                           d|             |                     ||         di | j	        
                    |i                      v|S )N)rc   r;   r   mesh_part_distance
mesh_partsz	expect: [,z
], found: r)   )rD   r7   rt   r   r   r   joinkeysrh   r   r   )r   vertex_groupsMAPnames       r   get_vertex_groupsr   
  s    M8*9* C  G Gs{{{N(<(<NNNN{{{YSYEE):):4)D)DEEFFFFr!      r   r   rv   r   c           	      
   dd l d}d}d}t          j        |d d df         |d d df         |d d df         gd          }                                        | t          j        ||g          j        j        	          g
          }                    g d          }	|		                    |           
                    ||||          }
i }t          j        g dg dddd|gg dgt          j                  |d<   t          j        g dg dddd| gg dgt          j                  |d<   t          j        g dddd| gg dg dgt          j                  |d<   t          j        g dddd|gg dg dgt          j                  |d<   t          j        ddd| gg dg dg dgt          j                  |d<   t          j        ddd|gg dg dg dgt          j                  |d<   |                                D ]\  }}|		                    |
||           fd|	                                D             }                    ||          }t          j        |||f          \  }}}t          j        |                                |                                |                                fdt          j                  }t          j        |                                |                                |dz
  |                                z
  fdt          j                  dz  |z  dz
  d|z  z   }i }|D ]d}||	_        |j        }|                    |	j        j        j        j        j        j        z            }||||k     <   ||z   ||z  |z  z
  }|||<   e|d d df          |d         |dz
  |d d df         z
  |d d df         f         z   |k    }||d d df         |d         |dz
  |d d df         z
  |dz
  |d d df         z
  f         z   |k    z  }|d d df          |d         |dz
  |d d df         z
  |dz
  |d d df         z
  f         z   |k    }||d d df         |d         |dz
  |d d df         z
  |d d df         f         z   |k    z  }|d d df          |d         |d d df         |d d df         f         z   |k    }||d d df         |d         |dz
  |d d df         z
  |d d df         f         z   |k    z  }||z  ||z  z  ||z  z  }||         }||         }||fS ) Nr   g?g      @g       @r   r   r<   r   )	positionsindicesr   )
primitives)r   r   r   r   )bg_color)xmagymagznearzfar)r   r   r   r   )r   r   r   r   )r   r   r   r   dtypez+z)r<   r   r   r   z-zz+y)r   r<   r   r   z-yz+xz-x)r   posec                 L    g | ] }t          |j                  |j        |!S r-   )
isinstanceNodecamera).0nodepyrenders     r   
<listcomp>z voxelization.<locals>.<listcomp>Z  s3    vvvT*T8=:Y:Yv^b^i^uD^u^u^ur!   )viewport_widthviewport_height)r>   r   r   )flags)r   rN   stackMesh	PrimitiveconcatenateGLTF	TRIANGLESSceneaddOrthographicCamerark   r   items	get_nodesOffscreenRendererr   ravelint64main_camera_noder   render	constantsRenderFlags
DEPTH_ONLY	OFFSCREEN)r`   r   rv   r   r   r   eye_disr_facesmeshscener   camera_posesr   r   camera_nodesrendererr[   jr]   r   r   depthscam_node
proj_depthmask_zmask_xmask_yr   r   s                               @r   r   r     s    OOOEDGhaaadU111a4[%1+>RHHHG=="w'788],   
   D NNLLLN11E	IIdOOO((e%uSW(XXFL 	
Aq'	#
 Z  L 
QrG8	#
 Z  L 	
Ab7(	#
 Z  L 	
Aq'	#
 Z  L 	
Ab7(	#
 Z  L 
Q7	#
 Z  L #((** 0 0
d		&t$	////vvvvU__%6%6vvvL))t)TTHj$d+,,GAq!8QWWYY		17799=ARXVVVL(AGGIIqwwyy$q&2BC!SUS]^^^abbeiiloorux|r||KF  " "!)}__U(2D2P2[^f^p^|  _G  3G_  H  H
'+
:e#$T\UT\Z$??
!t!!!Q$&,tAvl111a46H/H,WXWXWXZ[W[J\/\"]]ahhF
k!!!Q$&,tAvl111a46H/H$q&Q]^_^_^_ab^bQcJc/c"ddhoooF!!!Q$&,tAvl111a46H/H$q&Q]^_^_^_ab^bQcJc/c"ddhooF
k!!!Q$&,tAvl111a46H/H,WXWXWXZ[W[J\/\"]]ahhhF!!!Q$&,|AAAqD/A<PQPQPQSTPTCU/U"VVZaaF
k!!!Q$&,tAvl111a46H/H,WXWXWXZ[W[J\/\"]]ahhhFVO0FVODD%Ld#K$$r!   ry   r{   r}   r   r   r   rx   rz   r|   r~   r   r   c           
      	   |
dv sJ |j         d         }|j         d         }|j         d         }t          |          }t          |          }t          |          }t          j        ||gd          }|                    ||          \  }}|d d dd f         }|d d dd f         }d|k     |d| z  dz  k     z  }t          j        t          j        |          |dz
            |                                         |z   }||         |z   }||         |	z  }|                    |d          \  }}|d d dd f         }|d d dd f         }d|k     ||dz  k     z  }t          j        t          j        |          d          |                                         }||         }||         }|                    ||          \  }}d|k     |d| z  dz  k     z  }t          j        t          j        |          |          |                                         |z   }||         }||         }t          |          }|                    |          \  }} t          j        |d d df         |d d df         |d d df         gd          }!t          j        |d d df         |d d df         |d d df         gd          }"t          j        ||!         ||"         z
  dz  	                    d	                    }#t          t          j        ||#||g          t          j        ||!||gd          t          j        ||"||gd          ff||z   ||z   f
          }$t          |$dd|           }%|%d d d |f         }&t          j        |&                              d          }'t          |d          }(|                    ||'         |(          \  }}t          j        |'          d         })|}*t          j        |)|(                              d	|(          }+||&|*|+f<   |&t          j        |&                   },t          j        |,          }-t          j        |&|-|-|-          }&t          j        |&d          }&|
dk    rt          j        |& |-z  dz            }.n+|
dk    rdd|z
  |&z  ||&dz  z  z   z  dz  }.nJ d|
             |.|.	                    d          z  }.|.                                }.|.S )N)r   expr   r   r   r   gjt?      r<   rS   DF)methoddirectedr   r   r@   r  g      4@r   r   zinvalid mode: )rS   r   rN   r   queryrepeatr   r   sqrtrA   r   r   isinfallr   wherereshapeisfiniter   r   maximumr  	transpose)/rv   r   rH   r`   r   rx   rz   r|   r~   r   r   rX   MN	grid_treevertex_tree
joint_treecombined_verticesdistidxr   source_grid2gridto_grid2gridweight_grid2gridsource_closeto_closeweight_closesource_grid2vertexto_grid2vertexweight_grid2vertexcombined_tree_joint_indicessource_vertex2vertexto_vertex2vertexweight_vertex2vertexgraphdist_matrixdis_vertex2jointunreachabler]   unreachable_indicesrow_indicescol_indicesfinite_valsmax_disr;   s/                                                  r   r   r   |  sU    $$$$$QA!AqA$$I(##KJ
 +'>QGGG Z88ID#122;D
aaae*CH$u,-Dy1z!|<<TZZ\\JQNt9q=LDzK/ !!(A..ID#122;D
aaae*CH./D9RYq\\1--djjll;L4yH:L !!+|<<ID#H$u,-D29Q<<>>tzz||LqPYNd -..M$**622A} >5A;aaadU111a4[*QXYZZZ~uQQQT{E!!!Q$Kqqq!t&MTUVVV7X.B%ChO_F`%`cd$d#i#ioq#i#r#rss	';=MOab	c	cNL*>@PRdelmnnnNH&6nU\]^^^	`	

 sAaCj  E  cE=YYYK #111bqb5)(+,,00a088KAq		A  +!6::ID# (;//2K)/33;;BBBK15[+-."2;/?#@#@AKf[!!G}%577[bcccz"2D99u}}v'''1D899			QuW..7G7J1JJKaO--t----u$((("""D>>DKr!   c                    | j         d         }g }|D ]M}|\  }}}|                    ||g           |                    ||g           |                    ||g           Nt          j        |          }|dddf         }|dddf         }	t          j        t          |          t                    }
t          |
||	ff||f          }||j        z   }t          |dd          \  }}||dddf                  }|||fS )	z
    Find connected components of a mesh.
    
    Returns:
        int: number of connected components
        ndarray: labels of connected components
    r   Nr   r   r  FT)r  return_labels)
rS   rh   rN   rk   rT   rj   rr   r   Tr   )r`   r   r  rI   facev0v1v2rowcoldata
adj_matrixr   r   r   s                  r   r   r     s%    	qAE  
Bb"Xb"Xb"XHUOOE
1+C
1+C73u::S)))DTC:.q!f===Jjl*J-j5X\]]]Caaad,K{**r!   r   r   r]   c           
      H   | j         d         }g }g }|D ]}|\  }	}
}t          j                            | |	         | |
         z
            }t          j                            | |
         | |         z
            }t          j                            | |         | |	         z
            }|                    |	|
g|
|g||	gg           |                    |||g           t          j        |          }t          j        |          }|d d df         }|d d df         }t          |||ff||f          }||j        z   }t          j        ||ft          j	                  }t          |          D ]2}||k    }t          j        |          d         }t          |          }|dk    r9||k    r(t          j                            |          d |         }nUt          j        t          j                            |          t          j                            d|||z
            g          }||         }t#          ||d          }|d d |f         j        }|                                }|                                }||dz   k     rd|d<   n||z
  ||z
  z  }|||d d f<   4|S )	Nr   r   r  F)r   r  r@   rR   .)rS   rN   rO   rP   extendrk   r   r?  fullinfrU   r  rj   randompermutationr   randintr   r   r   )r`   r   r   r   r]   r  rI   weightsr@  rA  rB  rC  w01w12w20rD  rE  rG  distance_matrixcomponent_idcomponent_maskcomponent_vertices_idxn_componentsampled_indicessampled_verticesr5  	max_value	min_values                               r   r   r     s   qAEG ( (
BinnXb\HRL899innXb\HRL899innXb\HRL899r2hR2r(3444S#''''HUOOEhwG
1+C
1+CWsCj1!Q@@@Jjl*Jgq!fbf--Oc

 9 9'<7!#.!9!9!!<011!! i33K@@!DOO n	%%k22	!!![!k/BB.  O 2/B#J8HSXYYY!!!!^"346OO%%	OO%%	y4'''!K&2y97LMK-8)**r!   d   dim
iterationslrc           	      R   | dk    rd S t           j                            | |          }|t           j                            |dd          z  }t          j        |ddd          }t          |          D ]}|t           j        d d d d f         |d d t           j        d d f         z
  }t          j        |dz  d          }d|dz   z  }|t          j        ||d d d d t           j        f         z  |z  d          z  }|t           j                            |dd          z  }|S )	Nr   r   Tr=   r   r   r   r   )	rN   rL  randnrO   rP   r   rU   rW   rA   )	r   r]  r^  r_  vectorsr/  diffnorm_sqweights	            r   r   r   2  s.   
axxtiooc3''G	wQFFFGmGSEEEG: K Krz111aaa'(7111bj!!!3C+DD&+++w|$26$111bj(8!99B>QGGGGBINN7TNJJJNr!   )r   F)r   r   )ry   r{   r}   r}   r   r   )r\  r   )/platformossystemenvirontypingr   r   r   dataclassesr	   collectionsr
   abcr   r   numpyrN   r   scipy.spatialr   scipy.sparser   scipy.sparse.csgraphr   r   r2   r   specr   r   r+   r7   rD   rt   r   r   floatboolrl   r   rr   r   r&   r   r   r   r   r)   r!   r   <module>ru     s    				8?&+BJ"# $ $ $ $ $ $ $ $ $ $ ! ! ! ! ! ! # # # # # # # # # # # # # #           ! ! ! ! ! ! # # # # # # D D D D D D D D            

 
 
 
 

 
 
 
&    #   
 
 
 
 
k 
 
 
A
 A
 A
 A
 A
+ A
 A
 A
F0
 0
 0
 0
 0
; 0
 0
 0
d
 
 
 
 
+ 
 
 
,	 	 	 	 	; 	 	 	$ 3 333 3 	3
 3 3 
3 3 7G3 3 3 3j/ D4E    " 	b% b%b%b% b% 	b% b% b% b%T e e
ee e 	e
 e e e e e e e e e eN+ + +E#w,DW + + + +62g 2g 2V] 2dg 2lo 2t{ 2 2 2 2h  3 C  W^      r!   