
    MiI                        S r SSKrSSKJrJrJr  SSKJr  SSK	J
r
Jr  SSKJr  SSKJrJrJr  SS	KJrJrJr   SSKJr  SS
KJr      SS\S\S\S\4S jjr     S S\S\S\\   S\S\S\S\4S jjrS!S jr S r!S r"          S"S jr#     S#S jr$   S$S jr%         S%S jr&g! \ a4  rSSKJr  \R8                  " \5      r\R8                  " \5      r SrCNSrCff = f)&za
registration.py
---------------

Functions for registering (aligning) point clouds with meshes.
    N   )boundstransformationsutil)weighted_vertex_normals)
PointCloud	plane_fit)transform_points)anglescrossnormals)	ArrayLikeIntegerOptional)cKDTree)
exceptionssamplesscale	icp_first	icp_finalc                 @   S n[         R                  " U S5      (       d  [        S5      eSnU n	[         R                  " US5      (       av  [        U R                  5      [        UR                  5      :  a  Un	SnU" XS9n
U nOUnU" XS9n
UR
                  (       a  UR                  nOZUR                  R                  nOC[         R                  " US5      (       a  Un
[        R                  " U
5      S   nO[        S	5      eU	R
                  (       a  U	R                  nOU	R                  R                  n[        R                  " [        R                  R                  U5      U5      n[        R                  " / S
Q/ SQ/ SQ/ SQ/ SQ/ SQ/ SQ/ SQ4 Vs/ s H1  n[        R                   " S5      [        R"                  " US5      -  PM3     sn5      n[        R$                  " [        U5      5      [        R&                  -  nS/[        U5      -  nU	R(                  n[+        U5       Hw  u  nn[        R                  " [,        R.                  " UU5      [        R                  R                  U5      5      n[1        SU
U	U[3        U5      US.UD6u  nnnUUU'   UUU'   My     [1        SU
U	U[        R4                  " U5         [3        U5      US.UD6u  nnnU[        U
5      -  nU(       a#  [        R                  R                  U5      nUU4$ UnUU4$ s  snf )a)  
Align a mesh with another mesh or a PointCloud using
the principal axes of inertia as a starting point which
is refined by iterative closest point.

Parameters
------------
mesh : trimesh.Trimesh object
  Mesh to align with other
other : trimesh.Trimesh or (n, 3) float
  Mesh or points in space
samples : int
  Number of samples from mesh surface to align
scale : bool
  Allow scaling in transform
icp_first : int
  How many ICP iterations for the 9 possible
  combinations of sign flippage
icp_final : int
  How many ICP iterations for the closest
  candidate from the wider search
kwargs : dict
  Passed through to `icp`, which passes through to `procrustes`

Returns
-----------
mesh_to_other : (4, 4) float
  Transform to align mesh to the other object
cost : float
  Average squared distance per point
c           	          [        U R                  5      US-  :  aG  [        R                  " U R                  U R	                  U[        U R                  5      -
  5      45      $ U R	                  U5      $ )z
Return a combination of mesh vertices and surface samples
with vertices chosen by likelihood to be important
to registration.
   )lenverticesnpvstacksamplemcounts     n/var/www/eduai.edurigo.com/storigo/production/storigo_env/lib/python3.13/site-packages/trimesh/registration.py
key_pointsmesh_other.<locals>.key_pointsF   sT     qzz?eai(99ajj!((53qzz?3J*KLMM88E?"    Trimeshzmesh must be Trimesh object!TFr      r   z$other must be mesh or (n, 3) points!)r   r   r   )r   r   r(   )r   r(   r   )r(   r   r   )r(   r(   r   )r(   r   r(   )r   r(   r(   )r(   r(   r(      r   N)abinitialmax_iterationsr    )r   is_instance_named
ValueErrorr   r   	is_volumeprincipal_inertia_transformbounding_box_orientedis_shaper   oriented_boundsr   dotlinalginvarrayeyeappendonesinfcentroid	enumerater   transform_aroundicpintargmin)meshotherr   r   r   r   kwargsr#   inversesearchpointspoints_mesh
points_PIT
search_PITsearch_to_pointsdiagcubescosts
transformsr?   iflipa_to_bmatrix_junkcostmesh_to_others                              r"   
mesh_otherrZ      s   R	# !!$	22788GFeY//t}}ENN 33 FG$6FKK%7F  $@@J$::VVJ	ug	&	&++F3A6
?@@ 77
11MM

 vvbiimmJ7D HH 		
	 FF1I		$**		
E" GGCJ"&&(E#e*$JHU#4 ,,T8<IIMM*+
 " 
y>
 
t 
1a) $.  

299U+,9~ FE4 	CKD
 		f- $ $	
s   8Lr+   r,   weights
reflectiontranslationreturn_costc                    [         R                  " U [         R                  S9n[         R                  " U[         R                  S9n[        R                  " US5      (       a  [        R                  " US5      (       d  [        S5      e[        U5      [        U5      :w  a  [        S5      eUc  [         R                  " [        U5      5      n[         R                  " [         R                  " U[         R                  S9S5      n	[        U	5      [        U 5      :w  a  [        S5      eXR                  5       -  R                  S5      n
U
SS2S4   S	:  nX{   nX   nX   n
U(       a#  X-  R                  SS
9nX-  R                  SS
9nOF[         R                  " UR                  S   5      n[         R                  " UR                  S   5      nU(       aY  [         R                  " X-
  S-  U
-  R                  5       5      n[         R                  " X-
  S-  U
-  R                  5       5      nOSnSn[         R                  " X-
  U-  R                  X-
  U-  5      n[         R                   R#                  U5      u  nnnU(       a  [         R                  " UU5      nOu[         R                  " [         R                  " U[         R$                  " SS[         R                   R'                  [         R                  " UU5      5      /5      5      U5      nUUU-  [         R                  " UU5      -  -
  n[         R(                  " UU-  U-  UR                  SS5      45      n[         R*                  " U[         R,                  " S	/U R                  S   -  S/-   5      R                  SS5      45      nU(       a-  [/        UU5      nUUU   -
  S-  U
-  R                  5       nUUU4$ U$ )a  
Perform Procrustes' analysis to quickly align two corresponding
point clouds subject to constraints. This is much cheaper than
any other registration method but only applies if the two inputs
correspond in order.

Finds the transformation T mapping a to b which minimizes the
square sum distances between Ta and b, also called the cost.

Optionally filter the points in a and b via a binary weights array.
Non-uniform weights are also supported, but won't yield the optimal rotation.

Parameters
----------
a : (n,3) float
  List of points in space
b : (n,3) float
  List of points in space
weights : (n,) float
  List of floats representing how much weight is assigned to each point.
  Binary entries can be used to filter the arrays; normalization is not required.
  Translation and scaling are adjusted according to the weighting.
  Note, however, that this method does not yield the optimal rotation for
  non-uniform weighting,
  as this would require an iterative, nonlinear optimization approach.
reflection : bool
  If the transformation is allowed reflections
translation : bool
  If the transformation is allowed translation and rotation.
scale : bool
  If the transformation is allowed scaling
return_cost : bool
  Whether to return the cost and transformed a as well

Returns
----------
matrix : (4,4) float
  The transformation matrix sending a to b
transformed : (n,3) float
  The image of a under the transformation
cost : float
  The cost of the transformation
dtyper'   points must be (n,3)!z+a and b must contain same number of points!Nr   z)weights must have same length as a and b!)r(   r           axisr   r   r(         ?)r   
asanyarrayfloat64r   r5   r1   r   r=   maximumsumreshapezerosshapesqrtr7   Tr8   svdrO   dethstackr   r:   r
   )r+   r,   r[   r\   r]   r   r^   
a_original
b_originalww_normnonzero_weights	a_nonzero	b_nonzeroacenterbcenterascalebscaletargetu_svhRrV   transformedrX   s                             r"   
procrustesr      s)   j q

3Jq

3J==W--T]]:w5W5W011
:#j/)FGG''#j/*


2==

;Q?A
1vQDEE%%'k""7+F
 QTlS(O+I+I$F %***2%***2((9??1-.((9??1-.  I/A5?DDFGI/A5?DDFG
 VVi)V366):MQW9WYF		f%IAr2FF1bM FF266!RWWaBIIMM"&&B-,H%IJKRP
 Vf_q'0BBBKYY!+[-@-@Q-GHIFYY#!''!*)=)E F N NqRT UVWF&z6: k/::q@FJOOQ{D((Mr%   c                     [         R                  " U [         R                  S9n [        R                  " U S5      (       d  [        S5      eUc  [         R                  " S5      n[        R                  " US5      nU(       dU  [         R                  " U[         R                  S9n[        R                  " US5      (       d  [        S5      e[        U5      n[        X5      n Un[         R                  n	[        U5       Hx  n
U(       a  UR                  R                  U 5      u  pnOWR                  U S5      u  pX   n[        SXS.UD6u  nnnUn [         R                   " UU5      nU	U-
  U:  a    OUn	Mz     UWW4$ )	aY  
Apply the iterative closest point algorithm to align a point cloud with
another point cloud or mesh. Will only produce reasonable results if the
initial transformation is roughly correct. Initial transformation can be
found by applying Procrustes' analysis to a suitable set of landmark
points (often picked manually).

Parameters
----------
a : (n,3) float
  List of points in space.
b : (m,3) float or Trimesh
  List of points in space or mesh.
initial : (4,4) float
  Initial transformation.
threshold : float
  Stop when change in cost is less than threshold
max_iterations : int
  Maximum number of iterations
kwargs : dict
  Args to pass to procrustes

Returns
----------
matrix : (4,4) float
  The transformation matrix sending a to b
transformed : (n,3) float
  The image of a under the transformation
cost : float
  The cost of the transformation
r`   r'   rb   r*   r&   r   )r+   r,   r/   )r   rg   rh   r   r5   r1   r;   r0   r   r
   r>   rangenearest
on_surfacequeryr   r7   )r+   r,   r-   	thresholdr.   rG   is_meshbtreetotal_matrixold_cost_closest	_distance_faces
_distancesixrV   r   rX   s                      r"   rB   rB   ?  sN   B 	arzz*A==G$$011&&)$$Q	2GMM!2::.}}Q((455
 	$AL vvH >")*)=)=a)@&G"[[A.NJeG %/$H$H$H!T vvfl3d?Y&H% #( d**r%   c                 v   [         R                  " US5      (       d6  [        U[        5      (       d!  [        R
                  " U5      n[        U5      nU R                  U R                  pTU R                  US S S 24   -
  U-  U l        UR                  US S S 24   -
  U-  Ul        Ub  X$S S S 24   -
  U-  nXXE4$ )Nr&   )	r   r0   
isinstancer   r   rg   r?   r   r   )source_meshtarget_geometrytarget_positionsr   r?   r   s         r"   _normalize_by_sourcer     s     !!/9==jG G ==1$X.!**K,=,=e'008D!G3DDMK / 8 88D!G;L LPUUO#,a/@@EIh==r%   c                 ,   XPR                   -  US S S 24   -   U l         XQR                   -  US S S 24   -   Ul         Ub  XR-  US S S 24   -   n[        U[        5      (       a   U Vs/ s H  oeU-  US S S 24   -   PM     nnU$ XS-  US S S 24   -   nU$ s  snf )N)r   r   list)r   r   r   resultr?   r   xs          r"   _denormalize_by_sourcer     s     !#7#77(47:KKK$'?'??(4QR7BSSO# 3htQw6GG&$9?@A!)htQw//@ M (47"33M As   %Bc                    S nS nS nS nS n[        XU5      u  pnn[        U R                  5      n[        U R                  5      nU R                  R	                  5       nU" U S5      n[
        R                  " SSSU/5      n[        R                  " UU5      nU" U R                  5      nU" U R                  5      nU" U5      nU" UXU5      u  nnUc  / SQ/ S	Q/ S
Q/ SQ/nU(       a  U/nU GH  u  nn n!n"U	(       d  US:  a  Sn![
        R                  " [
        R                  5      R                  n#[
        R                  " [
        R                  5      R                  n$Sn%U#U$-
  U:  d  M  U"b  U%U":  d  M  [        UUU	(       + U!S:  U!S:  =(       a    U
US9n&[
        R                  " U5      n'SU'U&S   U:  '   U!S:  av  SU&;   ap  U&S   n(U
(       a  SU&;   a  U&S   n(UU-  n)[         R"                  " U)U(5      n*U	(       a  [
        R$                  " U*SS5      O[
        R&                  " U*5      n*U'U*U!-  -  n'U" UUU'U&S   UUUUUU 5
      nUU-  nU$n#[
        R(                  R+                  U&S   U-
  SS9n+U+U'-  R-                  5       n$U(       a  WR/                  U5        U%S-  n%U#U$-
  U:  d  GM  U"c  GM@  U%U":  a  GMI  GM     U(       a  Wn,OUn,[1        XUU,UU5      n,U,$ )a
  
Non Rigid Iterative Closest Points

Implementation of "Amberg et al. 2007: Optimal Step
Nonrigid ICP Algorithms for Surface Registration."
Allows to register non-rigidly a mesh on another or
on a point cloud. The core algorithm is explained
at the end of page 3 of the paper.

Comparison between nricp_amberg and nricp_sumner:
  * nricp_amberg fits to the target mesh in less steps
  * nricp_amberg can generate sharp edges
      * only vertices and their neighbors are considered
  * nricp_sumner tend to preserve more the original shape
  * nricp_sumner parameters are easier to tune
  * nricp_sumner solves for triangle positions whereas
    nricp_amberg solves for vertex transforms
  * nricp_sumner is less optimized when wn > 0

Parameters
----------
source_mesh : Trimesh
    Source mesh containing both vertices and faces.
target_geometry : Trimesh or PointCloud or (n, 3) float
    Target geometry. It can contain no faces or be a PointCloud.
source_landmarks : (n,) int or ((n,) int, (n, 3) float)
    n landmarks on the the source mesh.
    Represented as vertex indices (n,) int.
    It can also be represented as a tuple of triangle
    indices and barycentric coordinates ((n,) int, (n, 3) float,).
target_positions : (n, 3) float
    Target positions assigned to source landmarks
steps : Core parameters of the algorithm
    Iterable of iterables (ws, wl, wn, max_iter,).
    ws is smoothness term, wl weights landmark importance, wn normal importance
    and max_iter is the maximum number of iterations per step.
eps : float
    If the error decrease if inferior to this value, the current step ends.
gamma : float
    Weight the translation part against the rotational/skew part.
    Recommended value : 1.
distance_threshold : float
    Distance threshold to account for a vertex match or not.
return_records : bool
    If True, also returns all the intermediate results. It can help debugging
    and tune the parameters to match a specific case.
use_faces : bool
    If True and if target geometry has faces, use proximity.closest_point to find
    matching points. Else use scipy's cKDTree object.
use_vertex_normals : bool
    If True and if target geometry has faces, interpolate the normals of the target
    geometry matching points.
    Else use face normals or estimated normals if target geometry has no faces.
neighbors_count : int
    number of neighbors used for normal estimation. Only used if target geometry has
    no faces or if use_faces is False.

Returns
----------
result : (n, 3) float or List[(n, 3) float]
    The vertices positions of source_mesh such that it is registered non-rigidly
    onto the target geometry.
    If return_records is True, it returns the list of the vertex positions at each
    iteration.
c
                    X2S S 2S 4   -  n
US L=(       a    US LnX@-  UR                  US S 2S 4   5      /nSU-  U-   S4nU(       a-  UR                  X-  5        SU-  U-   UR                  S   -   S4n[        R                  " [        R
                  " U5      5      n[        R                  " U[        R                  S9nXSU-  SU-  U-   2S S 24'   U(       a)  X-  USU-  U-   SU-  U-   UR                  S   -   2S S 24'   [        R                  R                  UR                  U-  UR                  U-  5      R                  5       nU$ )Nr*   r)   r   r`   )multiplyr<   rm   sparse
csr_matrixr   
lil_matrixr   float32r8   spsolvero   toarray)M_kron_GDvertices_weightr   wsnEnVDlUlwlUuse_landmarksA_stackB_shapeABXs                    r"   _solve_system#nricp_amberg.<locals>._solve_system  s<   ag..$92T>=!**_QW-E"FGr6B;"NN27#2v{RXXa[0!4GfmmG45gRZZ8'(!b&AFRK
 !
#$>@gAa"frkQVb[288A;67:;MM!!!##'13373;;=r%   c                    U R                   R                  5       S-   n[        U R                   5      n[        R                  " [        R
                  " U5      S5      nU R                   R                  5       n[        R                  " SU-  [        R                  5      nSUSS S2'   U(       az  [        R                  R                  U R                  U R                   S S 2S4      U R                  U R                   S S 2S4      -
  SS9nU[        R                  " SU-  S5      -  n[        R                  " XdU44X24S9$ )Nr   r   r(   r   rd   rm   )edgesmaxr   r   repeatarangeflattenr=   r   r8   normr   r   
coo_matrix)rE   	do_weightr   r   rowscolsdataedge_lengthss           r"   _node_arc_incidence)nricp_amberg.<locals>._node_arc_incidence  s    ZZ^^!_yy2*zz!!#wwq2vrzz*QTT
99>>djjA./$--

1a4@P2QQXZ * L BIIa,.22D  $t!5bXFFr%   c                 P   [        U 5      n[        R                  " [        R                  " U5      S5      n[        R                  " SU-  5      n[        R                  " U [        R
                  " US45      4SS9R                  5       n[        R                  " XBU44USU-  4S9$ )Nr*   r   r(   rd   r   )	r   r   r   r   concatenater=   r   r   r   )vertex_3d_datar   r   r   r   s        r"   	_create_Dnricp_amberg.<locals>._create_D  s     yy2*yyR ~~~rwwAw/?@rJRRT  $t!5b!b&\JJr%   c                     [         R                  " [         R                  " S5      [         R                  " / SQ/5      4SS9n[         R                  " XS45      $ )Nr)   )r   r   r   r   rd   r   )r   r   r;   r:   tile)r   X_s     r"   	_create_Xnricp_amberg.<locals>._create_X'  s=    ^^RVVAY)(=>QGwwr7##r%   c                     Su  pEUb  Uc  XE4$ [        U[        5      (       GaO  Uu  pgUR                  U   nXR                  5       S S 24   nU=R                  UR                  5       R                  [        R                  " UR                  5      5      -  sl        UR                  US S 2S4      n	UR                  US S 2S4      n
UR                  US S 2S4      nUXS S 2SS 4   -  -
  XS S 2SS 4   -  -
  nUXS S 2SS 4   -  -
  XS S 2SS 4   -  -
  nUXS S 2SS 4   -  -
  XS S 2SS 4   -  -
  n[        R                  " UR                  S   S-  S45      nXSS S2'   XSS S2'   XSS S2'   XE4$ XS S 24   nUnXE4$ )N)NNr   r   r   r)   )r   tuplefacesr   r   r   r   diffindptrr   rl   rm   )r   r   source_landmarksr   r   r   source_tidssource_baryssource_tri_vidsx0x1x2Ul0Ul1Ul2s                  r"   _create_Dl_Ul#nricp_amberg.<locals>._create_Dl_Ul,  s   #'7'?6M&..(8%K)//<O**,a/0BGG|++-44RWWRYY5GHHG%%oad&;<B%%oad&;<B%%oad&;<B Aq$J//0Aq$J//0  !Aq$J//0Aq$J//0  !Aq$J//0Aq$J//0 
 399Q<!+Q/0Bqt!tHqt!tHqt!tH v Q&'B!Bvr%   Tr   ){Gz?
         ?r   )g{Gz?   r   r   )gQ?g      @r   r   )r   r   rc   r   r)   r   from_vertices_onlyreturn_normalsreturn_interpolated_normalsneighbors_count	distancesr   interpolated_normalsr   r(   rd   )r   r   r   r   copyr   rO   r   kronvertex_normalsfinfor   r   float16
_from_meshr=   r   diagonal_dotclipabsr8   r   meanr<   r   )-r   r   r   r   stepsepsgammadistance_thresholdreturn_records	use_facesuse_vertex_normalsr   r   r   r   r   r   r?   r   r   r   transformed_verticesMGr   r   DNr   r   r   recordsr   r   wnmax_iter
last_errorerrorcpt_iterqresr   target_normalssource_normalsr7   	error_vecr   s-                                                r"   nricp_ambergr    s   `"GK$
'R :N&6:6Ox
 
[	B	[!!	"B '//446K.A
Aq% !A{{1a H+&&'A	;--	.B"A1k=MNFB } 	
 '( !&BH _q0BXXbjj)--
$(( 5 3&H,<8@S$'0=!Av,.F,I7I /D !ggbkOFGOD-0BBCAv)t+!%i%*@D*H%)*@%AN!#a''G,5bggc1a(266#;"1CG"; !_d9or2r2rSUA $%q5 J		tI9M'MTVWI0668E34MHG 5 3&H,<8@S@S !&` %#&6%F Mr%   c                 h   [         R                  " U5      n[        U[        U R                  5      5      nU(       d  [        U R
                  5      S:X  a!  [        U R                  UU R                  UUS9$ 0 nSSKJ	n	  SSK
Jn
  U	" X5      u  US'   US'   US'   U(       a  U R                  US      US	'   U(       d  U(       an  U
" U R                  U R
                  US         US   5      US
'   U(       a;  [         R                  " SUS
   U R                  U R
                  US         5      US'   U$ )a  
Find the the closest points and associated attributes from a Trimesh.

Parameters
-----------
mesh : Trimesh
    Trimesh from which the query is performed
input_points : (m, 3) float
    Input query points
from_vertices_only : bool
    If True, consider only the vertices and not the faces
return_barycentric_coordinates : bool
    If True, return the barycentric coordinates
return_normals : bool
    If True, compute the normals at each closest point
return_interpolated_normals : bool
    If True, return the interpolated normal at each closest point
neighbors_count : int
    The number of closest neighbors to query
kwargs : dict
    Dict to accept other key word arguments (not used)
Returns
----------
qres : Dict
  Dictionary containing :
   - nearest points (m, 3) with key 'nearest'
   - distances to nearest point (m,) with key 'distances'
   - support triangle indices of the nearest points (m,) with key 'tids'
   - [optional] normals at nearest points (m,3) with key 'normals'
   - [optional] barycentric coordinates in support triangles (m,3) with key
     'barycentric_coordinates'
   - [optional] interpolated normals (m,3) with key 'interpolated_normals'
r   )r   r   r   )closest_point)points_to_barycentricr   r   tidsr   barycentric_coordinatesz
ij,ijk->ikr   )r   rg   minr   r   r   _from_pointskdtree	proximityr  	trianglesr  face_normalseinsumr   )rE   input_pointsr   return_barycentric_coordinatesr   r   r   rG   r  r  r  s              r"   r   r     s    V ==.L/3t}}+=>OS_1MMKK)+
 	
 D(07DT7X4DOT+&V++DL9Y%)D*?MM$**T&\23T)_+
&' '+-99./##DJJtF|$<=,D'(
 Kr%   c                    [         R                  " U 5      n [         R                  " U5      n[        U[        U 5      5      n0 nUc  [	        U 5      nU(       aX  US:  d   eUR                  XS9u  pxXSS24   n	[        U	5      S   US'   U	SS2S4   US'   USS2S4   US'   USS2S4   US	'   U$ UR                  U5      u  US'   US	'   XS	   SS24   US'   U$ )
a'  
Find the the closest points and associated attributes
from a set of 3D points.

Parameters
-----------
target_points : (n, 3) float
  Points from which the query is performed
input_points : (m, 3) float
  Input query points
kdtree : scipy.cKDTree
  KDTree used for query. Computed if not provided
return_normals : bool
  If True, compute the normals at each nearest point
neighbors_count : int
  The number of closest neighbors to query
kwargs : dict
  Dict to accept other key word arguments (not used)

Returns
----------
qres : Dict
  Dictionary containing :
   - nearest points (m, 3) with key 'nearest'
   - distances to nearest point (m,) with key 'distances'
   - vertex indices of the nearest points (m,) with key 'vertex_indices'
   - [optional] normals at nearest points (m,3) with key 'normals'
Nr)   )kr   r   r   r   r   vertex_indices)r   rg   r  r   r   r   r	   )
target_pointsr  r  r   r   rG   r  r   indicesr   s
             r"   r  r    s   J MM-0M==.L/3}+=>OD~'!####\\,\J	
+#G,Q/Y!!Q$-Y%adO[!(A
 K 5;LL4N1[4 01'-=(>(ABYKr%   c           
        ^4^5 U44S jm4S nU44S jnU44S jnS nS nU54S jn[        XU5      u  pnn[        U R                  5      m5USL=(       a    USLnUc  / S	Q/ S	Q/ S
Q/ SQ/nU" U 5      u  nnn[        R                  R                  U5      nU
S:X  a  U R                  nOU R                  nU" UUU5      u  nnU" UUUU5      u  nnU" UX5      u  nnUR                  5       nU(       a  UST5 /n [        U5       GHV  u  n!u  n"n#n$n%n&UU#-  UU$-  /n'UU#-  UU$-  /n(U(       a(  U'R                  UU%-  5        U(R                  UU%-  5        U!S:  d  U(       GdG  U"S:  Ga@  [        UUST5 U(       + U&S:  U=(       a    U&S:  U	S9n)U" U)S   U[        U5      5      u  n*n+[        R                  " T55      n,SU,U)S   U:  '   U&S:  d  SU);   a~  U)S   n-U(       a  SU);   a  U)S   n-U" UU R                  5      n.[        R                  " U.U-5      n/U(       a  [        R                   " U/SS5      O[        R"                  " U/5      n/U,U/U&-  -  n,U*=R$                  U,U   U*R&                     -  sl        U+U,US4   -  n+U'R                  U*U"-  5        U(R                  U+U"-  5        [(        R*                  " U'SS9n0U0R-                  5         [        R.                  " U(5      n1[(        R                  R1                  U0R2                  U0-  R5                  5       5      n2U2R7                  U0R2                  U1-  5      nU(       d  GMB  W R                  UST5 5        GMY     U(       a  W n3OUST5 n3[9        XUU3UU5      n3U3$ )a
  
Non Rigid Iterative Closest Points

Implementation of the correspondence computation part of
"Sumner and Popovic 2004: Deformation Transfer for Triangle Meshes"
Allows to register non-rigidly a mesh on another geometry.

Comparison between nricp_amberg and nricp_sumner:
  * nricp_amberg fits to the target mesh in less steps
  * nricp_amberg can generate sharp edges
      * only vertices and their neighbors are considered
  * nricp_sumner tend to preserve more the original shape
  * nricp_sumner parameters are easier to tune
  * nricp_sumner solves for triangle positions whereas
    nricp_amberg solves for vertex transforms
  * nricp_sumner is less optimized when wn > 0

Parameters
----------
source_mesh : Trimesh
    Source mesh containing both vertices and faces.
target_geometry : Trimesh or PointCloud or (n, 3) float
    Target geometry. It can contain no faces or be a PointCloud.
source_landmarks : (n,) int or ((n,) int, (n, 3) float)
    n landmarks on the the source mesh.
    Represented as vertex indices (n,) int.
    It can also be represented as a tuple of triangle indices and barycentric
    coordinates ((n,) int, (n, 3) float,).
target_positions : (n, 3) float
    Target positions assigned to source landmarks
steps : Core parameters of the algorithm
    Iterable of iterables (wc, wi, ws, wl, wn).
    wc is the correspondence term (strength of fitting), wi is the identity term
    (recommended value : 0.001), ws is smoothness term, wl weights the landmark
    importance and wn the normal importance.
distance_threshold : float
    Distance threshold to account for a vertex match or not.
return_records : bool
    If True, also returns all the intermediate results. It can help debugging
    and tune the parameters to match a specific case.
use_faces : bool
    If True and if target geometry has faces, use proximity.closest_point to find
    matching points. Else use scipy's cKDTree object.
use_vertex_normals : bool
    If True and if target geometry has faces, interpolate the normals of the target
    geometry matching points.
    Else use face normals or estimated normals if target geometry has no faces.
neighbors_count : int
    number of neighbors used for normal estimation. Only used if target geometry has
    no faces or if use_faces is False.
face_pairs_type : str 'vertex' or 'edge'
    Method to determine face pairs used in the smoothness cost. 'vertex' yields
    smoother results.


Returns
----------
result : (n, 3) float or List[(n, 3) float]
    The vertices positions of source_mesh such that it is registered non-rigidly
    onto the target geometry.
    If return_records is True, it returns the list of the vertex positions at each
    iteration.
c                   > [         R                  " / SQS-  5      T	l        [        U5      n[         R                  " T	R                  U5      S[         R
                  " [         R                  " U5      S5      -  -   n[         R
                  " U R                  S5      nUR                  SS9* nUR                  US5      n[         R                  " Xg4SS9R                  5       n[        R                  " XU44SU-  U4[        S	9$ )
N)r   r   r   r*   r)      r   rd   	   r(   )rm   ra   )r   r:   _rowr   r   r   r   flatrj   rk   r   r   r   r   float)
r   Vinvsizer   r   r   minus_inv_sum	Vinv_flatr   _construct_transform_matrixs
            r"   r/  1nricp_sumner.<locals>._construct_transform_matrix  s    +-88IM+B#(Yww277<q299IIbM2D
 @
 
 yyQ'q))LLQ'	~~}8rBJJL  $t!5a"fd^SXYYr%   c                    U R                   nU R                  S S 2S4   nU R                  S S 2S4   nU R                  S S 2S4   nX!-   n[        R                  " U R                  U45      n[        U R                  5      [        U R                  5      p[        R                  " XwU-   5      S S 2S 4   n	[        R                  " U R                  U	4SS9n
[        R                  " X2-
  S   XB-
  S   US   4SS9nXjU4$ )Nr   r   r   r(   rd   ).N)r  r  r   r   r   r   r   r   )rE   v4_vecv1v2v3v4r   r   nT
v4_indicestetrahedronsframess               r"   _build_tetrahedrons)nricp_sumner.<locals>._build_tetrahedrons  s    ""^^AqD!^^AqD!^^AqD![>>4==""56T]]#S_BYYr7+AtG4
~~tzz:&>RHgy!BGY#7	9JKRT
 v--r%   c                    > T" UU[        U 5      5      R                  5       n[        R                  " [        R                  " S[
        S9[        U5      S45      nX44$ )Nr)   r`   r   )r   tocsrr   r   identityr*  )vtettetr+  AEiBir/  s        r"   _construct_identity_cost.nricp_sumner.<locals>._construct_identity_cost  sR    )I
 %'	 	
 WWR[[%03s8Q-@wr%   c                 b  > T" XS S 2S4      X#S S 2S4      [        U 5      5      R                  5       nT" XS S 2S4      X#S S 2S4      [        U 5      5      R                  5       nXE-
  R                  5       nUR                  5         [        R
                  " [        U5      S-  S45      nXg4$ )Nr   r   r)   )r   r>  tocsceliminate_zerosr   rl   )	r@  rA  r+  
face_pairsAEs_rAEs_lAEsBsr/  s	           r"   _construct_smoothness_cost0nricp_sumner.<locals>._construct_smoothness_cost  s    +1a4 !41a4(8#93t9

%' 	 ,1a4 !41a4(8#93t9

%' 	 }##%XXs:*A./wr%   c                    Uc.  S [         R                  " [        UR                  5      [        S94$ [        U[        5      (       a  Uu  p4UR                  U   n[        U5      [        U 5      pv[         R                  " [         R                  " U5      S5      nUR                  n	UR                  n
[        R                  " XU	44Xg4S9nUU[         R                  " [         R                  5      R                  :     n[         R                  " [        UR                  5      [        S9nSX'   X4$ [        U5      [        U 5      pv[         R                  " U5      nUR                  n	[         R                  " U5      n
[        R                  " XU	44Xg4S9n[         R                  " [        UR                  5      [        S9nSX'   X4$ )Nr`   r)   r   F)r   r=   r   r   boolr   r   r   r   r   r)  r   r   r   r   r   )r@  r   r   source_landmarks_tidssource_landmarks_baryssource_landmarks_vidsnLnVTr   r   r   AElmarker_vidsnon_markers_masks                 r"   _construct_landmark_cost.nricp_sumner.<locals>._construct_landmark_cost  s   #[%9%9!:$GGG&..<L9!$/$5$56K$L!/0#d)99RYYr]A.D(--D)..D##T$<$8	JC/&"**)=)A)AAK  "wws;+?+?'@M,1) $$ *+SY99R=D#((D772;D##T$<$8	JC!wws;+?+?'@M16.$$r%   c                 d    [         R                  " U[        SS9S [        U5       nX1   nX   nX44$ )Ncsc)ra   format)r   r?  r*  r   )rJ   rY  r,  AEcBcs        r"   _construct_correspondence_cost4nricp_sumner.<locals>._construct_correspondence_cost  s9    ood%>?VEUAVW#%wr%   c                 l   > X   n[        U5      n[        X#S9S   n[        U5      n[        TUUUS9nU$ )N)r  crossesr   )vertex_countr   r  face_angles)r   r   r   r   )r   r   mesh_trianglesmesh_triangles_crossmesh_face_normalsmesh_face_anglesmesh_normalsr   s          r"   _compute_vertex_normals-nricp_sumner.<locals>._compute_vertex_normals  sV    !$^4#$

 ".1.*(	
 r%   N)r   MbP?rf     r   )r   rn  rf   ro  r   )d   rn  rf   ro  r   vertexr   r   r   r   r   r   r   r]  )r^  )r   r   r   r   r8   r9   face_neighborhoodface_adjacencyr   r@   r<   r   r=   r   r   r   r   r   r   r#  r   r   rH  r   spluro   rG  solver   )6r   r   r   r   r   r   r   r   r  r   face_pairs_typer;  rD  rN  rZ  ra  rl  r?   r   r   source_vtet
source_tetVr+  rI  rB  rC  rL  rM  rW  rY  r  r  rS   wcwir   r   r  AstackBstackr  r_  r`  r   r  r  r7   r   r,   LUr   r/  r   s6                                                       @@r"   nricp_sumnerr  @  s   ZZ. %>" <P&6<8_% 
[!!	"B$D0Q5ET5QM} %$%&
 "5[!AKQ99==D (" 22
 //
 '{JEGC(j$
SGC4[C	 '++-',- $-U#3BBB(C"H%r'27#MM#(#MM*R/0EBF$Sb)'0=!Av-?-JBF /D 5Y!13{3CGC !ggbkOFGOD-0BBCAvd*!%i%*@D*H%)*@%AN!8(+*;*;" ''G,5bggc1a(266#;"1CG"; HH(89#++FFH/"2D"899BMM#(#MM"r'" MM&/	NN6"]]q 12!xxa0 >NN/45o $4r %cr*#&6%F Mr%   )i  Fr   2   )NTTTT)Ngh㈵>   )
NNNg-C6?r   皙?FTT   )FFFFr   )NFr   )	NNNr  FTTr  rq  )'__doc__numpyr    r   r   r   geometryr   rJ   r   r	   r
   r  r   r   r   typedr   r   r   scipy.sparser   scipy.spatialr   BaseExceptionEr   ExceptionWrapperrQ  rZ   r   rB   r   r   r  r   r  r  r/   r%   r"   <module>r     s    + + - ) - - - / /	,!% b b 	b
 b bP $(zzz i z 	z
 z z zzK+\>"( 

DT #( %Ld 8| 
`Y  , ))!,G((+F,s   B1 1C+7*C&&C+