
    }j[R                       d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	m
Z
 ddlmZ ddlZ ej                  d      Z e
d       G d	 d
             Z eddddddddd	       eddddddddd	       edddd d!d"d#d$d%	       ed&dd'ddd(d)d)d*	       ed+d,d-dd.d/d0d1d2	      fZdHd3ZdId4Zdd5	 	 	 	 	 	 	 dJd6Z	 	 	 	 	 	 	 	 	 	 dKd7ZdLd8ZdMd9Zdd:d;	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dNd<ZdOd=Z	 	 	 	 	 	 	 	 	 	 	 	 dPd>Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dQd?Zdd@	 	 	 	 	 	 	 	 	 	 	 dRdAZdSdBZdSdCZ	 	 	 	 	 	 	 	 dTdDZ 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dUdEZ!dVdFZ"e#dGk(  r e"        yy)Wa  Feature-aware, topology-preserving mesh denoising experiments.

The implementation follows the two-stage family used by guided mesh-normal
filtering: robustly filter face normals, then move the *existing* vertices
toward the planes described by those normals.  It adds safeguards needed for
this product asset: a hard displacement trust region, feature/boundary locks,
mostly-normal motion, data fidelity, and reflection-field diagnostics.
    )annotationsN)asdict	dataclass)Pathg#B;T)frozenc                  h    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   y)Configstrnameintguide_iterationsnormal_iterationsfloatnormal_sigmavertex_iterationsvertex_step	data_pullmax_displacement_diagonaltangent_ratioN)__name__
__module____qualname____annotations__     a/home/vela/workspace/domain/tn-silver/web/tn-site/.runtime/model-denoise-research/denoise_mesh.pyr	   r	      s7    
I$$r   r	   gentle      g333333?   gp=
ף?g
ףp=
?g~jtH?gQ?balanced      g
ףp=
?
   gףp=
?gy&1?g~jtX?g{Gz?strong      g)\(?   gffffff?g;On?g~jth?g?wide   =
ףp=?g~jtx?gQ?deep   2   .   g)\(?gMbp?g{Gz?gQ?c            	     D   t        j                         } | j                  dd       | j                  dd       | j                  ddt        D cg c]  }|j                   c}t        D cg c]  }|j                   c}       | j                         S c c}w c c}w )Nz--inputT)requiredz--outdirz
--variants+)nargsdefaultchoices)argparseArgumentParseradd_argumentCONFIGSr   
parse_args)parserconfigs     r   r:   r:   1   s    $$&F
	D1

T2
+233+233	    43s   B-Bc                    t         j                  j                  | d      }| t        j                  |d d d f   t              z  S )N   axis)nplinalgnormmaximumEPS)valueslengthss     r   normalize_rowsrH   >   s7    iinnV!n,GBJJwq$w/555r   need_centroidsc                   | |d d df      | |d d df      z
  }| |d d df      | |d d df      z
  }t        j                  ||      }t         j                  j                  |d      }|t        j                  |d d d f   t
              z  }d }|r<| |d d df      | |d d df      z   | |d d df      z   t        j                  d      z  }|j                  t         j                        |dz  j                  t         j                        |fS )Nr>   r   r   r?         @      ?)rA   crossrB   rC   rD   rE   float32astype)	verticesfacesrJ   edge_aedge_bcrossesdouble_areanormals	centroidss	            r   face_geometryrY   C   s    eAqDk"XeAqDk%::FeAqDk"XeAqDk%::Fhhvv&G))..q.1K

;q$w#7==GIU1a4[!uQT{#$uQT{#$ JJsO		
 >>"**%c(9'A'A"**'MyXXr   c                   ||d d d f   z  }t        j                  | t         j                        }t        d      D ]o  }|d d |f   }t        d      D ]V  }|d d |fxx   t        j                  ||d d |f   t        |             j                  t         j                        z  cc<   X q t        |      j                  t         j                        S )Ndtyper"   weights	minlength)rA   
zeros_likerO   rangebincountlenrP   rH   )	rQ   rR   
face_areasface_normalsweightedresultcornerindicesr@   s	            r   vertex_normalsrj   U   s     jD11H]]82::6F( !6	"!H 	!D1d7Or{{ D)h-  fRZZ 	!O	!! &!((44r   c                   t        |       }t        j                  |dz  dft        j                        }| dddf   |ddd<   | dddf   |ddd<   | ddd	f   |ddd<   |j	                  d
       t        j
                  t        j                  |t        j                        d      }|dddf   j                  t        j                        t        j                  d      z  |dddf   j                  t        j                        z  }t        j                  |d      }||   }t        j                  t        j                  d|dd |dd k7  f         j                  t        j                        }t        j                  |dd t        |      f   }	|	|z
  }
||   }||   j                         }|
dk(  }||   }||   }||dz      }t        j                  ||   ||   f      j                  t        j                        }||   j                         }|
dk(  }||||         j                         }t        j                  |t               }t        |      rd||j#                         <   t%        t        |            t%        t        j&                  |            t%        t        j&                  |
dkD              d}~~~~~~~	~
t)        j*                          |||||dS )z;Build edge-adjacent face pairs without Python dictionaries.r"   r   r[   N)r   r>   r   )r>   r   r>   )r   r   r?       stable)kindT)unique_edge_countboundary_edge_countnonmanifold_edge_count)unique_edgesadjacent_facesadjacent_edgesboundary_verticesstats)rc   rA   emptyint32sortrepeatarangerP   uint64argsortflatnonzeror_int64copycolumn_stackzerosboolravelr   count_nonzerogccollect)rR   vertex_count
face_count	raw_edgesownerskeysordersorted_keysgroup_starts
group_endsgroup_countsunique_indicesrs   manifoldstarts	raw_first
raw_secondrt   ru   boundary_groupsboundary_edgesrv   rw   s                          r   build_topologyr   e   s   UJ*q.!,BHH=IAvI&IaddOAvI&IaddOAvI&IaddONNNYYryy288<a@FadO""299-2>)AqD/BXBX
		C D JJt(+Eu+K>>
dKO{3B'7778fRXX  |AB'[)99:J,L<(N^,113Lq H(#FfIvz"J__fY&7
9K%LMTTUWU]U]^Ny)..0N"a'Ou\/%BCDIIKNT:
>48...01 !\!23"2#3#3O#DE"%b&6&6|a7G&H"IE
 	64\:|JJL$((. r   c                H   d}d}t        dt        |      |      D ]n  }||||z    }| |d d df      | |d d df      z
  }|t        t        j                  j                  |d      j                  t        j                              z  }p |t        t        |      d      z  S )N        i  r   r>   r?   r[   )	ra   rc   r   rA   rB   rC   sumfloat64max)rQ   edgestotalchunkstartpartdeltas          r   mean_edge_lengthr      s    EEq#e*e, LUUU]+ad$xQT
';;ryy~~e!~488rzz8JKKL 3s5z1%%%r         ?)fixed_guidanceblendc               R   |dddf   }|dddf   }| j                         }	t        j                  |t        j                  |      z  t        j                  d            }
t        j
                  |
t        j                  d            j                  t        j                        }
t        |      D ]  }||	n|}t        j                  d||   ||         }t        j                  t        j                  dddt        j                  |d	d
      z  z
              }t        j                  dt        j                  ||z        z        j                  t        j                        }|	|
dddf   z  }|
j                         }||f||ffD ]  \  }}||
|   z  }|t        j                  ||t        |	            j                  t        j                        z  }t        d      D ]W  }|dd|fxx   t        j                  |||	||f   z  t        |	            j                  t        j                        z  cc<   Y  t        |t        j                  |dddf   t               z        }t        d
|z
  |	z  ||z  z         j                  t        j                        }	 |	S )z;Area-weighted bilateral diffusion over edge-adjacent faces.Nr   r>   g-C6?g       @ij,ij->ir          @      r   g      r]   r"   )r   rA   rD   medianrO   minimumrP   ra   einsumsqrtclipexpsquarerb   rc   rH   rE   )rW   rd   rt   
iterationssigmar   r   leftrightcurrent
area_scale_guidancedotsnormal_distancepair_weightaccumulated
weight_sumdestinationsourcer^   r@   updateds                          r   diffuse_normalsr      sL    !Q$D1a4 EllnGJ:)>>

4@PQJJ

38??

KJ: _,47.yyXd^Xe_E''"**S#bggdDRU>V8V2V"WXffTBIIo.E$FFGNNrzzZ
1d7 33__&
%)5ME4=#A 
	%K!Jv$66G"++WGfRZZ !J a %AtG$#gfdl&;;!'l) &$	%$%
	% !rzz*QW:Ms/S!ST #+!857?!JKRRSUS]S]^)_* Nr   c                ^    t        j                  || z
  || z
  z  dd      }||z  dd|z  z
  z  S )Nr   r   rL   r   )rA   r   )edge0edge1rF   scaleds       r   
smoothstepr      s9    WWfun7cBFF?cC&L011r   c                r   |d d df   |d d df   }}t        j                  d| |   | |         }t        j                  t        j                  dddt        j                  |dd      z  z
              }t        dd	|      j                  t         j                        }	t        j                  |t         j                  
      }
t         j                  j                  |
|d d df   |	       t         j                  j                  |
|d d df   |	       d|
|<   |
|j                  t         j                        fS )Nr   r>   r   r   r   r   r   )\(?g?r[   )
rA   r   r   rD   r   r   rP   rO   r   at)r   rt   ru   rv   r   r   r   r   distanceedge_strengthvertex_strengths              r   feature_protectionr      s     !A&q!t(<%D99Z$%ADwwrzz#sS2774s3K-K'KLMHtT84;;BJJGMhh|2::>OJJMM/>!Q$#7GJJMM/>!Q$#7G),O%&HOOBJJ777r   c                   | j                         }t        j                  t        |      t        j                        }t        d      D ]I  }	|t        j                  |d d |	f   t        |            j                  t        j                        z  }K t        j                  |d      }t        j                  ||j                  z        }
t        |j                        D ]  }||d d df      ||d d df      z   ||d d df      z   t        j                  d      z  }t        j                  |t        j                        }t        d      D ]  }	|d d |	f   }t        j                  d	||||   z
        }||d d d f   z  }t        d      D ]V  }|d d |fxx   t        j                  ||d d |f   t        |      
      j                  t        j                        z  cc<   X  ||d d d f   z  }|dd|d d d f   z  z
  z  }|t        j                  |j                        |z  z   }|| z
  }t        j                  d	||      }||d d d f   z  }||z
  }|t        j                  |j                        |z  z   }|t        j                  d|j                  z
        z  }t        j                   j#                  |d      }t        j$                  d|
t        j                  |t&              z        j                  t        j                        }||d d d f   z  }||j)                  dt        j*                        j                  t        j                        z  }| |z   } |j                  t        j                        S )Nr[   r"   )r_   r   r   r>   r   rL   r   r]   gq=
ףp?r?   )r@   r\   )r   rA   r   rc   rO   ra   rb   rP   rD   r   r   r`   r   r   r   r   rB   rC   r   rE   meanr   )original_verticesrR   target_normalsoriginal_vertex_normalsfeature_strengthr<   diagonalrQ   countsrh   trust_radiusr   rX   
correctionri   residual	projectedr@   proposeddisplacementnormal_amountnormal_parttangent_partrG   scales                            r   update_verticesr      s)    !%%'HXXc(m2::6F( \"++eAvI.#h-HOOPRPZPZ[[\ZZ$F::h)I)IIJL6++, 4U1a4[!HU1a4[$99HU1a4[<QQJJsO	 ]]82::>
Ah 		%FAvI&Gyy^YRYIZ=Z[H&!T')::Ia %1d7#r{{%ag.!(m( &$	%#%			% 	fQWo%
sT$4QW$===>
bjj););<zII"33		*l<ST-ag0FF#k1"RZZ0D0D%E%TT

3)9)9#9::))..A.6

3rzz'3/G GHOOPRPZPZ[ag&))q

)CJJ2::VV$|3?4@ ??2::&&r   )
max_passesc                  |j                         }t        j                  t        |      t              }t        |      D ]  }t        ||d      \  }}	}t        j                  d||      }
|
dk  |	dk  z  }t        j                  |      s n5t        j                  ||   j                               }d||<   | |   ||<    |t        t        j                  |            fS )a  Restore vertices incident to inverted/degenerate faces.

    The inputs can contain a few extremely small triangles where even a tiny
    trusted displacement changes orientation.  Reverting their incident
    vertices is conservative and affects a negligible fraction of the mesh.
    r[   FrI   r   r   g+=T)r   rA   r   rc   r   ra   rY   r   anyuniquer   r   r   )r   candidate_verticesrR   original_face_normalsr   rQ   revertedr   rW   areas	alignmentunsaferi   s                r   revert_unsafe_facesr     s     "&&(HxxHT2H: 7)(E%PIIj*?I	s"u~6vvf~))E&M//12 -g67 S))(3444r   c                x    t        | |d      \  }}}t        |j                  t        j                              S )NFrI   r[   )rY   r   r   rA   r   )rQ   rR   r   r   s       r   surface_arear   2  s0    %FKAua,--r   c                (   d}d}t        dt        |      |      D ]q  }||||z    }t        j                  | |d d df      | |d d df            }|t	        t        j
                  d| |d d df      |t        j                              z  }s |dz  S )	Nr   i r   r>   r   zij,ij->r[   g      @)ra   rc   rA   rN   r   r   r   )rQ   rR   r   r   r   trirN   s          r   signed_volumer   7  s    EEq#e*e, [EEEM*#ad),hs1a4y.ABryyHSAY,?bjjYZZ[ 3;r   c                   |d d df   }|d d df   }t        j                  dt         j                        }g }|D ]  }| |z  }d|d d d f   z  | z  |d d d f   z
  }	|	|   |	|   z
  }
t        j                  d|
|
      }|j	                  t        t        j                  t        j                  ||   t         j                                            t        t        j                  |            S )Nr   r>   ))r   r   r   )r   g(%g(%?)g!nk?g!nkۿg!nk?)缡:gUUr   g1UU?r[   r   r   )	rA   asarrayrO   r   appendr   r   r   r   )rW   rt   smooth_maskr   r   viewsrF   viewr   	reflectedr   squareds               r   reflection_rmsr   A  s     !Q$D1a4 EJJ	
 jjE F W~$q$w-''1DqMA	$)E"22))Ju5eBGGBGGGK,@

$STUVW !!r   c
                   t        ||d      \  }
}}t        j                  j                  || z
  d      }|d d df   |d d df   }}t        j                  d|
|   |
|         }t        j
                  t        j                  dddt        j                  |d	d
      z  z
              }t        j                  d||
      }t        ||      }t        t        ||            }t        |j                  t        j                              t        t        j
                  t        j                  |dz  t        j                                    t        t        j                  |d            t        t        j                  |d            t        |j                               t        d|j                         z  |z        t        t        j                  |d      |z        t!        t        j"                  |dk              t        t        j$                  t        j&                  t        j                  |d	d
                  j                  t        j                              t        t        j
                  t        j                  t        j(                  ||         t        j                                    t+        |
||      |t        d||z  d
z
  z        |t        d||	z  d
z
  z        dS )NFrI   r>   r?   r   r   r   r   r   r   r[   r   gffffff?gGz?      Y@)displacement_meandisplacement_rmsdisplacement_p95displacement_p99displacement_maxdisplacement_max_pct_diagonaldisplacement_p95_in_mean_edgesflipped_facesnormal_change_mean_degreessmooth_region_normal_tv_rmsreflection_field_rmsr   surface_area_change_pctabsolute_volumevolume_change_pct)rY   rA   rB   rC   r   r   rD   r   r   absr   r   r   r   quantiler   r   r   degreesarccosr   r   )r   rQ   rR   original_normalsrt   r   r   	mean_edgeoriginal_areaoriginal_volumerW   r   r   r   r   r   normal_deltaface_alignmentareavolumes                       r   geometry_metricsr  Y  sH    "(E%HMGQ99>>(->">Q>GL A&q!t(<%D99Z?D772::c3rwwtT37O1O+OPQLYYz+;WEN%(Dx/0F"<#4#42::#4#FG!"''"'',/*T"UV!"++lD"AB!"++lD"AB!,"2"2"45).u|7G7G7I/IH/T)U*/L$0OR[0[*\R--n.CDE&+JJryys!CDEJJQSQ[Q[J\'
 (-GGBGGBIIl;&?@

ST(
 !/w T#($2F2L)M#N!"5F_,Ds,J#KL' r   c                    t               } t        | j                        j                         }t        | j                        j                         }|j                  dd       t        D ci c](  }|j                  | j                  v s|j                  |* }}t        j                  |      }t        j                  |d   t        j                        }t        j                  |d   t        j                        }|j                  d      |j                  d      z
  }t!        t        j"                  j%                  |            }	t'        dt)        |      d	d
t)        |      d	d       t+        j,                         }
t/        |t)        |            }|d   }|d   }|d   }|d   }t1        ||      }t'        dt)        |      d	dt)        |      d	d|d       t3        ||      \  }}}t5        ||||      }t!        |j7                  t        j8                              }t;        t=        ||            }t        d |j?                         D              }d|i}|jA                         }tC        d|dz         D ]&  }tE        |||ddd      }|jA                         ||<   ( ||   }|d d df   |d d df   }}t        jF                  d||   ||         }t        jH                  t        jJ                  dddt        jL                  |dd      z  z
              }|dk  } tO        |||||| |	|||
      }!tQ        |      tS        t)        |            tS        t)        |            |	|t!        t        jT                  |             |d   |!i d 	}"|jW                         D ]}  \  }#}t'        d!|# d"       ||jX                     }$t[        |$|||t)        |            \  }%}tE        ||||j\                  |j^                  |$d#$      }&t'        d!|# d%       ta        |||&||%||	      }'tc        ||'||      \  }'}(|d&|# d'z  })t        jd                  |)|'|(       tO        ||'|||| |	|||
      }*t!        d)d|*d*   |!d*   z  z
  z        |*d+<   t!        d)d|*d,   |!d,   z  z
  z        |*d-<   tg        |      tQ        |)      |*|(t!        t        jT                  |%d.kD              d/|"d0   |#<   t'        d!|# d1|*d-   d2d3|*d4   d5d6|*d7           ~&~'~%ti        jj                           t+        j,                         |
z
  |"d8<   |d9z  }+|+jm                  to        jp                  |"d:;      d<=       t'        d>|+ d?|"d8   d@dA       y c c}w )BNT)parentsexist_okrQ   r[   rR   r   r?   zLoaded ,z vertices / z
 trianglesrs   rt   ru   rv   z
Topology: z edges, z face pairs, mean edge z.8fc              3  4   K   | ]  }|j                     y w)N)r   ).0r<   s     r   	<genexpr>zmain.<locals>.<genexpr>  s     W6v66Ws   r>   g(\?r+   )r   r   r   r   r   r   r   r   r   rw   )	inputrQ   	trianglesbounds_diagonalr   smooth_face_pair_fractiontopologybaselinevariants[z] filtering normalsgQ?)r   r   r   r   z] projecting original verticesz	denoised-z.npz)rQ   rR   r  r  normal_tv_improvement_pctr  reflection_improvement_pctrM   )r<   outputmetrics!reverted_vertices_for_flip_safety$protected_vertex_fraction_over_50pctr*  z] reflection z.2fz% better; p95 displacement r  z.7fz; flips r	  elapsed_secondszdenoise-metrics.jsonr   )indentzutf-8)encodingzWrote z in z.1fs)9r:   r   r$  resolveoutdirmkdirr9   r   r*  rA   loadr   rO   ry   r   minr   rB   rC   printrc   timeperf_counterr   r   rY   rj   r   r   r  r   rF   r   ra   r   r   r   rD   r   r  r
   r   r   itemsr   r   r   r   r   r   savezr   r   r   
write_textjsondumps),args
input_pathr7  r<   selectedloadedr   rR   boundsr   startedr(  rs   rt   ru   rv   edge_lengthr   rd   r   r   r  r  max_guide_iterationsguidance_levelsr   	iterationmetric_guidancemetric_leftmetric_rightmetric_dotsmetric_distancer   r)  reportr   guide
protectionr   rQ   reverted_verticesoutput_pathr/  report_paths,                                               r   mainrX    s   <Ddjj!))+J$++&&(F
LLL-29ZV[[DMM=YV#ZHZWWZ F

6*#5RZZHJJvgbhh7E"""*->-B-B-B-JJFRYY^^F+,H	GC)*1-\#e*Qz
RS!GeS):%;<HN+L./N./N !45"#4lCK	
S&q)#n2Ea1H I %	'
 ,99JE+R(:q,5*.C *..rzz.:;M-(95ABOWX__EVWW./1F-GO$))+H12Q67 	5	"
 &.]]_	"	5 &&:;O .q!t 4nQT6JK))OK0/,2OK gg


3cBGGKs$CCCDO
 "D(KH Z-./U_#'%*277;+?%@W%
!F !( Bf$*+, 7 78*!"

A )!//%% 
 	$567"#
 ':x0E'
## 4&55
xu="!
 05W:;hGd>eeeg0
+, 16S7#9:XF\=]]]^1
,- Vn+&1B49"''*sBR:S4T$
z4  	v]7+G#H"M N  '(: ;C@ A_-.0	

 Hj


EBH !% 1 1 3g =F11K4::fQ7'J	F;-tF+<$=c#B!
DEk [s   ,V
V__main__)returnzargparse.Namespace)rF   
np.ndarrayrZ  r[  )rQ   r[  rR   r[  rJ   r   rZ  z0tuple[np.ndarray, np.ndarray, np.ndarray | None])
rQ   r[  rR   r[  rd   r[  re   r[  rZ  r[  )rR   r[  r   r   rZ  zdict[str, np.ndarray | int])rQ   r[  r   r[  rZ  r   )rW   r[  rd   r[  rt   r[  r   r   r   r   r   znp.ndarray | Noner   r   rZ  r[  )r   r   r   r   rF   r[  rZ  r[  )r   r[  rt   r[  ru   r[  rv   r[  r   r   rZ  ztuple[np.ndarray, np.ndarray])r   r[  rR   r[  r   r[  r   r[  r   r[  r<   r	   r   r   rZ  r[  )r   r[  r   r[  rR   r[  r   r[  r   r   rZ  ztuple[np.ndarray, int])rQ   r[  rR   r[  rZ  r   )rW   r[  rt   r[  r   r[  rZ  r   )r   r[  rQ   r[  rR   r[  r  r[  rt   r[  r   r[  r   r   r  r   r  r   r  r   rZ  zdict[str, float | int])rZ  None)$__doc__
__future__r   r6   r   rA  mathr<  dataclassesr   r   pathlibr   numpyrA   rO   rE   r	   r9   r:   rH   rY   rj   r   r   r   r   r   r   r   r   r   r   r  rX  r   r   r   r   <module>rc     s6   #  	    )   bjj $	 	 	 8Q4D%$?
:q"dBeWdC
8QD"dE7DA
62r4T5'4@
62r4T5'4@
6 HLYY!+Y@DY5Y$55!+59C5S]55 1h&" )-%%% % 	%
 % &% % %P2
888 8 "	8
 8 #8&0'!0'0' 0' (	0'
 !0' 0' 0' 0'r 5!5"5 5 &	5 5 58.
"")3"BL"
"0(!(( ( !	(
 ( ( ( ( ( ( (VZFz zF r   