§
    ÎÐj„3  ã                  óä   — d Z ddlmZ ddlZddlmZ ddlZddlZddl	m
Z
mZmZ dZh d£Zd	Zg d
¢Zej        fd,d„Zd-d„Zd.d„Zd/d.d„Zddœd0d„Zd1d„Zd2d„Zd3d„Zd0d„Zd4dd œd5d(„Zd6d*„Zd.d+„ZdS )7ac  Gaussian splats in the INRIA 3D Gaussian Splatting PLY layout, point clouds as splats, and plain point-cloud PLYs.

Splat dict (float32 torch tensors on one device; `ply_to_splats` / `points_to_splats` also return "comments"):
- means [N, 3]: centres, glTF axes (+Y up, +Z front; see splats_opencv_to_gltf for OpenCV-frame outputs);
- scales [N, 3]: LINEAR standard deviations along the local axes, in world units (the PLY stores log(scale));
- rotations [N, 4]: unit quaternions (w, x, y, z), local-to-world;
- opacities [N]: LINEAR opacities in 0..1 (the PLY stores logit(opacity));
- sh_dc [N, 3]: degree-0 spherical-harmonic coefficients, colour = 0.5 + SH_C0 * sh_dc (sRGB-like display values);
- sh_rest [N, K, 3] or None: higher degrees, K = (degree + 1)^2 - 1, in the 3DGS basis order;
- sh_degree: int.

PLY layout written (INRIA, binary little-endian, every property float32): x y z nx ny nz f_dc_0..2 f_rest_0..(3K-1)
opacity scale_0..2 rot_0..3, f_rest stored channel-major (all K red coefficients, then green, then blue), normals zero,
and a `comment sh_degree N` header line. Our own numpy code (no plyfile).
é    )ÚannotationsN)ÚPathé   )Ú_ply_headerÚ_read_ply_asciiÚ_read_ply_elementgm›BP×Ò?>   Úrot_0Úf_dc_0ÚopacityÚscale_0g�íµ ÷Æ°>)éÿÿÿÿr   r   r   r   r   r   r   r   r   r   r   r   r   r   Úreturnú
np.ndarrayc                óþ   — t          | t          j        ¦  «        rO|                      ¦   «                              d¬¦  «                             ¦   «                              |d¬¦  «        nt          j        | |¦  «        S )NÚcpu©ÚdeviceF)Úcopy)	Ú
isinstanceÚtorchÚTensorÚdetachÚtoÚnumpyÚastypeÚnpÚasarray)ÚvalueÚdtypes     ú<C:\Users\johnn\OneDrive\Documents\AI\shared\mesh3d\splats.pyÚ_arrayr!   "   s   € ÝPZÐ[`ÕbgÔbnÑPoÔPoð  Nˆ5�<Š<‰>Œ>×Ò EÐÑ*Ô*×0Ò0Ñ2Ô2×9Ò9¸%ÀeÐ9ÑLÔLÐLÕuwÔuð  AFð  HMñ  vNô  vNð  Nó    ÚdataÚbytesútuple[list[str], int]c                ó  — |                       d¦  «        }|                      d¦  «        r|dk     rt          d¦  «        ‚|                      d|¦  «        dz   }| d |…                              d¦  «                             ¦   «         |fS )Nó
   end_headers   plyr   zNot a PLY fileó   
r   úutf-8)ÚfindÚ
startswithÚ
ValueErrorÚindexÚdecodeÚ
splitlines)r#   ÚendÚbodys      r    Ú_header_textr2   &   sƒ   € Ø
�)Š)�MÑ
"Ô
"€CØ�?Š?˜6Ñ"Ô"ð + c¨A¢g gÝÐ)Ñ*Ô*Ð*Ø�:Š:�e˜SÑ!Ô! AÑ%€DØ���Œ;×Ò˜gÑ&Ô&×1Ò1Ñ3Ô3°TÐ9Ð9r"   c                ó  — t          | t          t          t          f¦  «        rQt          | dd…         ¦  «        }d|v r4|d|                     d|                     d¦  «        ¦  «        dz   …         n|S d}t          | d¦  «        5 }d|vsd||                     d¦  «        d…         vr@|                     d¦  «        }|sn(||z  }d|v°!d||                     d¦  «        d…         v°@ddd¦  «         n# 1 swxY w Y   |S )	zoThe PLY header bytes (up to and including the end_header line) of a path or bytes, reading only what is needed.Ni   r'   r(   r   r"   Úrbi   )r   r$   Ú	bytearrayÚ
memoryviewr-   ÚopenÚread)Úsourcer#   ÚhandleÚchunks       r    Ú_read_headerr<   .   s`  € å�&�5¥)­ZÐ8Ñ9Ô9ð jÝ�V˜H˜W˜HÔ%Ñ&Ô&ˆØJWÐ[_ÐJ_ÐJ_ˆtÐE�T—Z’Z  t§z¢z°-Ñ'@Ô'@ÑAÔAÀAÑEÐEÔFÐFÐeiÐiØ€DÝ	ˆf�dÑ	Ô	ð ˜vØ 4Ð'Ð'¨5¸¸T¿ZºZÈÑ=VÔ=VÐ=WÐ=WÔ8XÐ+XÐ+XØ—K’K Ñ(Ô(ˆEØð ØØ�E‰MˆDð	  4Ð'Ð'¨5¸¸T¿ZºZÈÑ=VÔ=VÐ=WÐ=WÔ8XÐ+XÐ+Xðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð €Ks   ÂA$C6Ã6C:Ã=C:© c                óT  — d„ | |||fD ¦   «         \  } }}}t          j        t          |t           j        ¦  «                             d¦  «        t
          dt
          z
  ¦  «        }|€/t          j        t          | ¦  «        ddft           j        ¦  «        nt          |¦  «        }t          j
        |j        d         dz   ¦  «        dz
  }|dz   dz  dz
  |j        d         k    rt          d|j        d         › d	�¦  «        ‚| t          j        | ¦  «        ||                     ddd¦  «                             t          | ¦  «        d¦  «        t          j        |d|z
  z  ¦  «        dd…df                              t           j        ¦  «        t          j        t          j        |d
¦  «        ¦  «        |g}	g d¢d„ t%          d|j        d         z  ¦  «        D ¦   «         z   }
|
g d¢z  }
|D ]}d|v sd|v rt          d¦  «        ‚Œddd|› �gd„ |D ¦   «         z   }|dt          | ¦  «        › �gd„ |
D ¦   «         z   dgz   z  }t          j        t          j        |	d¦  «        d¬¦  «        }d                     |¦  «        dz                        d¦  «        |                     ¦   «         z   S )zµINRIA 3DGS PLY bytes from linear scales / opacities (see the module docstring); torch tensors or numpy arrays.
    comments are extra header lines (`comment <text>`, one line each).c              3  ó4   K  — | ]}t          |¦  «        V — Œd S ©N)r!   )Ú.0Úvs     r    ú	<genexpr>z splats_to_ply.<locals>.<genexpr>@   s(   è è € Ð&\Ð&\°Q¥v¨a¡y¤yÐ&\Ð&\Ð&\Ð&\Ð&\Ð&\r"   r   r   Nr   é   é   zsh_rest has z% coefficients, not (degree + 1)^2 - 1ç ÂëþKH´9)	ÚxÚyÚzÚnxÚnyÚnzr
   Úf_dc_1Úf_dc_2c                ó   — g | ]}d |› �‘ŒS )Úf_rest_r=   )rA   Úis     r    ú
<listcomp>z!splats_to_ply.<locals>.<listcomp>H   s    € ÐNÐNÐNÐabÈ}ÐYZÈ}È}ÐNÐNÐNr"   )r   r   Úscale_1Úscale_2r	   Úrot_1Úrot_2Úrot_3ú
úú!PLY comments must be single linesÚplyúformat binary_little_endian 1.0zcomment sh_degree c                ó   — g | ]}d |› �‘ŒS ©úcomment r=   ©rA   Úcs     r    rR   z!splats_to_ply.<locals>.<listcomp>M   s#   € ÐY{ÐY{ÐY{ÐmnÐZhÐefÐZhÐZhÐY{ÐY{ÐY{r"   úelement vertex c                ó   — g | ]}d |› �‘ŒS )zproperty float r=   ©rA   Úns     r    rR   z!splats_to_ply.<locals>.<listcomp>N   s!   € Ð1WÐ1WÐ1WÈAÐ2GÀAÐ2GÐ2GÐ1WÐ1WÐ1Wr"   Ú
end_headerú<f4©r   r)   )r   Úclipr!   Úfloat64ÚreshapeÚ_OPACITY_EPSILONÚzerosÚlenÚfloat32ÚmathÚisqrtÚshaper,   Ú
zeros_likeÚ	transposeÚlogr   ÚmaximumÚrangeÚascontiguousarrayÚconcatenateÚjoinÚencodeÚtobytes)ÚmeansÚscalesÚ	rotationsÚ	opacitiesÚsh_dcÚsh_restÚcommentsÚrestÚdegreeÚcolumnsÚnamesÚcommentÚheaderr1   s                 r    Úsplats_to_plyrŠ   =   s¿  € ð ']Ð&\¸5À&È)ÐUZÐ:[Ð&\Ñ&\Ô&\Ñ#€Eˆ6�9˜eÝ”�˜y­"¬*Ñ5Ô5×=Ò=¸bÑAÔAÕCSÐUVÕYiÑUiÑjÔj€IØ7>°�2Œ8•S˜‘Z”Z  AÐ&­¬
Ñ3Ô3Ð3ÍFÐSZÉOÌO€DÝŒZ˜œ
 1œ¨Ñ)Ñ*Ô*¨QÑ.€FØ�‰
�qÑ˜1Ñ ¤
¨1¤Ò-Ð-ÝÐ\¨¬
°1¬Ð\Ð\Ð\Ñ]Ô]Ð]Ø•b”m EÑ*Ô*¨E°4·>²>À!ÀQÈÑ3JÔ3J×3RÒ3RÕSVÐW\ÑS]ÔS]Ð_aÑ3bÔ3bÝŒv�i 1 y¡=Ñ1Ñ2Ô2°1°1°1°d°7Ô;×BÒBÅ2Ä:ÑNÔNÕPRÔPVÕWYÔWaÐbhÐjoÑWpÔWpÑPqÔPqÐs|ð~€GàKÐKÐKÐNÐNÕfkÐlmÐptÔpzÐ{|Ôp}Ñl}Ñf~Ôf~ÐNÑNÔNÑ€EØ	Ð]Ð]Ð]Ñ]€EØð Bð BˆØ�7ˆ?ˆ?˜d g˜o˜oÝÐ@ÑAÔAÐAð .àÐ6Ð8UÈVÐ8UÐ8UÐVÐY{ÐY{ÐrzÐY{ÑY{ÔY{Ñ{€FØ
Ð-¥ U¡¤Ð-Ð-Ð.Ð1WÐ1WÐQVÐ1WÑ1WÔ1WÑWÐ[gÐZhÑhÑh€FÝÔ¥¤¨w¸Ñ :Ô :À%ÐHÑHÔH€DØ�IŠI�fÑÔ Ñ$×,Ò,¨WÑ5Ô5¸¿º¹¼ÑFÐFr"   r   r   Údictc               óL  ‡‡— t          | t          t          t          f¦  «        rt          | ¦  «        n t	          | ¦  «                             ¦   «         }t          |¦  «        \  }}}}t          d„ |D ¦   «         ¦  «        }|d         |urt          d¦  «        ‚|dk    r3t          ||d…          
                    d¦  «        |g¦  «        d         Šn!t          |||ddd	œ|         ¦  «        d
         Št          t          ‰¦  «        k    st          d¦  «        ‚ˆfd„}t          d„ ‰D ¦   «         d„ ¬¦  «        }	t          ‰d         ¦  «        }
ˆfd„} |dddd¦  «        } | |ddd¦  «        ¦  «         |t!          j         |ddd¦  «        ¦  «        ¦  «         ||t!          j        t           j                             |d
d¬¦  «        d¦  «        z  ¦  «         |d
d
t!          j        t!          j        ‰d         t           j        ¦  «         ¦  «        z   z  ¦  «         | |dd d!¦  «        ¦  «        |	r8 | ||	Ž                      |
d"d#¦  «                             dd$d
¦  «        ¦  «        ndt3          j        t          |	¦  «        d"z  d
z   ¦  «        d
z
  |d%œ}|S )&zÈSplat dict (see the module docstring, with linear scales and opacities, normalized rotations) of an INRIA 3DGS
    PLY file (path or bytes; binary or ASCII); "comments" holds the header comment lines.c              3  ó2   K  — | ]}|d          dk    ¯|V — ŒdS )ÚnameÚvertexNr=   )rA   Úes     r    rC   z ply_to_splats.<locals>.<genexpr>X   s0   è è € ÐGÐG °°6´¸hÒ1FÐ1F˜!Ð1FÐ1FÐ1FÐ1FÐGÐGr"   r   z1The vertex element must come first in a splat PLYÚasciiNr�   ú<ú>)Úbinary_little_endianÚbinary_big_endianr   úNot a Gaussian splat PLYc                 óF   •— t          j        ˆfd„| D ¦   «         d¦  «        S )Nc                óZ   •— g | ]'}t          j        ‰|         t           j        ¦  «        ‘Œ(S r=   )r   r   rj   )rA   re   r�   s     €r    rR   z3ply_to_splats.<locals>.<lambda>.<locals>.<listcomp>a   s+   ø€ Ð%WÐ%WÐ%WÈA¥b¤j°¸´½B¼JÑ&GÔ&GÐ%WÐ%WÐ%Wr"   r   )r   Ústack)r‡   r�   s    €r    ú<lambda>zply_to_splats.<locals>.<lambda>a   s*   ø€ �BœHÐ%WÐ%WÐ%WÐ%WÐQVÐ%WÑ%WÔ%WÐYZÑ[Ô[€ r"   c              3  óD   K  — | ]}|                      d ¦  «        ¯|V — ŒdS ©rP   N©r+   rd   s     r    rC   z ply_to_splats.<locals>.<genexpr>b   s3   è è € ÐFÐF˜q¨a¯lªl¸9Ñ.EÔ.EÐF˜ÐFÐFÐFÐFÐFÐFr"   c                ó0   — t          | dd …         ¦  «        S )Né   )Úint)re   s    r    rš   zply_to_splats.<locals>.<lambda>b   s   € ÕVYÐZ[Ð\]Ð\^Ð\^ÔZ_ÑV`ÔV`€ r"   )ÚkeyrG   c                óŽ   •— t          j        t          j        | t          j        ¬¦  «        ¦  «                             ‰¦  «        S )Nrh   )r   Ú
from_numpyr   rx   ro   r   )Úar   s    €r    rš   zply_to_splats.<locals>.<lambda>d   s3   ø€ •uÔ'­Ô(<¸QÅbÄjÐ(QÑ(QÔ(QÑRÔR×UÒUÐV\Ñ]Ô]€ r"   r	   rU   rV   rW   rH   rI   r   rS   rT   T)ÚaxisÚkeepdimsrF   r   r
   rM   rN   rD   r   rE   ©r}   r~   r   r€   r�   r‚   Ú	sh_degreerƒ   )r   r$   r5   r6   r   Ú
read_bytesr   Únextr,   r   r.   r   ÚSPLAT_PROPERTIESÚsetÚsortedrn   r   Úexprv   ÚlinalgÚnormr   rj   rk   rt   rp   rq   )r9   r   r#   ÚfmtÚelementsrƒ   ÚposÚvertex_elementÚcolumnÚ
rest_namesÚcountÚtensorr   Úsplatsr�   s    `            @r    Úply_to_splatsrº   S   sæ  øø€ õ ' vµµyÅ*Ð/MÑNÔNÐm�5�‰=Œ=ˆ=ÕTXÐY_ÑT`ÔT`×TkÒTkÑTmÔTm€DÝ#.¨tÑ#4Ô#4Ñ €Cˆ�8˜SÝÐGÐG XÐGÑGÔGÑGÔG€NØ�„{˜.Ð(Ð(ÝÐLÑMÔMÐMØ
ˆg‚~€~Ý   c d d¤×!2Ò!2°7Ñ!;Ô!;¸nÐ=MÑNÔNÈxÔXˆˆå" 4¨¨nÐWZÐqtÐ>uÐ>uÐvyÔ>zÑ{Ô{Ð|}Ô~ˆÝ�s 6™{œ{Ò*Ð*ÝÐ3Ñ4Ô4Ð4Ø[Ð[Ð[Ð[€FÝÐFÐF FÐFÑFÔFÐL`ÐL`ÐaÑaÔa€JÝ��s”ÑÔ€EØ]Ð]Ð]Ð]€FØ��w ¨°'Ñ:Ô:€IØ�v˜f˜f S¨#¨sÑ3Ô3Ñ4Ô4ÀÀÅrÄvÈfÈfÐU^Ð`iÐktÑNuÔNuÑGvÔGvÑ@wÔ@wØ!˜6 )­b¬j½¼¿ºÈ	ÐXYÐdh¸Ñ9iÔ9iÐkpÑ.qÔ.qÑ"qÑrÔrØ!˜6 ! q­2¬6µ2´:¸fÀYÔ>OÕQSÔQ[Ñ3\Ô3\Ð2\Ñ+]Ô+]Ñ']Ñ"^Ñ_Ô_ÐjpÐjpÐqwÐqwð  yAð  CKð  MUñ  rVô  rVñ  kWô  kWØakÐu˜˜  ¨
Ð 3× ;Ò ;¸EÀ1ÀbÑ IÔ I× SÒ SÐTUÐWXÐZ[Ñ \Ô \Ñ]Ô]Ð]ÐquÝœ:¥c¨*¡o¤o¸Ñ&:¸QÑ&>Ñ?Ô?À!ÑCÐQYð	[ð [€Fð
 €Mr"   ú	list[str]c                óX   — t          t          | ¦  «        ¦  «        \  }}d„ |D ¦   «         S )zZText of the `comment` header lines of a PLY file (path or bytes), reading only the header.c                óL   — g | ]!}|                      d ¦  «        ¯|dd…         ‘Œ"S )r_   é   Nr�   )rA   Úlines     r    rR   z ply_comments.<locals>.<listcomp>q   s1   € ÐFÐFÐF˜¨$¯/ª/¸*Ñ*EÔ*EÐFˆD���ŒHÐFÐFÐFr"   )r2   r<   )r9   ÚlinesÚ_s      r    Úply_commentsrÂ   n   s/   € å�L¨Ñ0Ô0Ñ1Ô1�H€Eˆ1ØFÐF ÐFÑFÔFÐFr"   c                ó  ‡— t          t          | d|                      d|                      d¦  «        ¦  «        dz   …         ¦  «        ¦  «        \  }}|D ]}d|v sd|v rt          d¦  «        ‚Œd„ |D ¦   «         Šˆfd	„|D ¦   «         }t	          d
„ t          |¦  «        D ¦   «         ¦  «        dz   }d„ |D ¦   «         |||…<   d                     |¦  «        dz                        d¦  «        t          | |d…         ¦  «        z   S )a3  PLY bytes with the given comment lines added to the header. An existing comment whose first word is the first
    word of a new comment is replaced (so rewriting "wangp {...}" replaces the previous settings and keeps
    "sh_degree 0"). Only the header changes; the data that follows is kept byte-identical.Nr(   r'   r   rX   rY   rZ   c                óF   — h | ]}|                      d d¦  «        d         ’ŒS )ú r   r   )Úsplitr`   s     r    ú	<setcomp>z%ply_write_comments.<locals>.<setcomp>|   s)   € Ð1Ð1Ð1 1ˆA�GŠG�C˜‰OŒO˜AÔÐ1Ð1Ð1r"   c                óŠ   •— g | ]?}|                      d ¦  «        r&|dd…                              dd¦  «        d         ‰v °=|‘Œ@S )r_   r¾   NrÅ   r   r   )r+   rÆ   )rA   r¿   Úkeyss     €r    rR   z&ply_write_comments.<locals>.<listcomp>}   sV   ø€ ÐnÐnÐn�T¨4¯?ª?¸:Ñ+FÔ+FÐnÈ4ÐPQÐPRÐPRÌ8Ï>Ê>ÐZ]Ð_`ÑKaÔKaÐbcÔKdÐhlÐKlÐKlˆDÐKlÐKlÐKlr"   c                óB   — g | ]\  }}|                      d ¦  «        ¯|‘ŒS ))zformat r_   r�   )rA   rQ   r¿   s      r    rR   z&ply_write_comments.<locals>.<listcomp>~   s.   € Ð[Ð[Ð[‘G�A�t°$·/²/ÐBYÑ2ZÔ2ZÐ[ˆaÐ[Ð[Ð[r"   c                ó   — g | ]}d |› �‘ŒS r^   r=   r`   s     r    rR   z&ply_write_comments.<locals>.<listcomp>   s   € Ð4Ð4Ð4 a�>˜a�>�>Ð4Ð4Ð4r"   r)   )r2   r$   r-   r,   ÚmaxÚ	enumeraterz   r{   )r#   rƒ   rÀ   r1   rˆ   ÚkeptÚatrÉ   s          @r    Úply_write_commentsrÐ   t   s&  ø€ õ �u TÐ*[¨4¯:ª:°e¸T¿ZºZÈÑ=VÔ=VÑ+WÔ+WÐZ[Ñ+[Ð*[Ô%\Ñ]Ô]Ñ^Ô^�K€Eˆ4Øð Bð BˆØ�7ˆ?ˆ?˜d g˜o˜oÝÐ@ÑAÔAÐAð .à1Ð1¨Ð1Ñ1Ô1€DØnÐnÐnÐn˜UÐnÑnÔn€DÝ	Ð[Ð[�y¨™œÐ[Ñ[Ô[Ñ	\Ô	\Ð_`Ñ	`€BØ4Ð4¨8Ð4Ñ4Ô4€DˆˆBˆ�KØ�IŠI�d‰OŒO˜dÑ"×*Ò*¨7Ñ3Ô3µe¸DÀÀÀ¼KÑ6HÔ6HÑHÐHr"   Úboolc                ór  — 	 t          t          | ¦  «        ¦  «        \  }}n# t          t          f$ r Y dS w xY wt	          ¦   «         d}}|D ]a}|                     ¦   «         }|dd…         dgk    r|dd…         dgk    }Œ5|dd…         dgk    r|r|                     |d         ¦  «         Œbt          |k    S )	zqTrue for a PLY whose vertex element has the 3DGS properties (f_dc_0, opacity, scale_0, rot_0); header sniff only.FNr   ÚelementrE   r�   Úpropertyr   )r2   r<   ÚOSErrorr,   r¬   rÆ   Úaddr«   )r9   rÀ   rÁ   r‡   Ú	in_vertexr¿   Úwordss          r    Úis_splat_plyrÙ   ƒ   sÙ   € ðÝ¥¨VÑ 4Ô 4Ñ5Ô5‰ˆˆqˆqøÝ•ZÐ ð ð ð Øˆuˆuðøøøå‘u”u˜eˆ9€EØð !ð !ˆØ—
’
‘”ˆØ��!�Œ9˜˜Ò#Ð#Ø˜a ˜cœ
 x jÒ0ˆIˆIØ�2�A�2ŒY˜:˜,Ò&Ð&¨9Ð&Ø�IŠI�e˜B”iÑ Ô Ð øÝ˜uÒ$Ð$s   ‚" ¢7¶7c                ó6  — t          t          | ¦  «        ¦  «        \  }}dt          ¦   «         ddf\  }}}}|D ]³}|                     ¦   «         }|dd…         dgk    r)|dd…         dgk    }|rt	          |d         ¦  «        n|}ŒN|dd…         dgk    r|r|                     |d	         ¦  «         Œ{|dd…         d
dgk    r(t          |¦  «        dk    rt	          |d         ¦  «        }Œ´t          |k    st          d¦  «        ‚|€4t          j
        t          d„ |D ¦   «         ¦  «        dz  dz   ¦  «        dz
  }t          | t          t          t          f¦  «        rt          | ¦  «        n%t!          | ¦  «                             ¦   «         j        }	d|||	dœS )a  Header-only statistics of a 3DGS splat PLY (path or bytes): {"format": "ply", "gaussians": N, "sh_degree": d
    (from the `comment sh_degree N` line, else from the f_rest_* count), "file_size": bytes}. Raises ValueError for a
    file that is not a splat PLY.r   FNr   rÓ   rE   r�   rÔ   r   rˆ   r¨   r–   c              3  ó@   K  — | ]}|                      d ¦  «        V — ŒdS rœ   r�   rd   s     r    rC   z#splat_file_stats.<locals>.<genexpr>¥   s.   è è € ÐGÐG¸A §¢¨YÑ 7Ô 7ÐGÐGÐGÐGÐGÐGr"   rD   r[   )ÚformatÚ	gaussiansr¨   Ú	file_size)r2   r<   r¬   rÆ   r    rÖ   rn   r«   r,   rp   rq   Úsumr   r$   r5   r6   r   ÚstatÚst_size)
r9   rÀ   rÁ   r·   r‡   r×   r…   r¿   rØ   Úsizes
             r    Úsplat_file_statsrã   “   s¦  € õ �L¨Ñ0Ô0Ñ1Ô1�H€Eˆ1Ø&'­©¬°°tÐ&;Ñ#€Eˆ5�)˜VØð #ð #ˆØ—
’
‘”ˆØ��!�Œ9˜˜Ò#Ð#Ø˜a ˜cœ
 x jÒ0ˆIØ%.Ð9•C˜˜aœ‘M”M�M°EˆEˆEØ�2�A�2ŒY˜:˜,Ò&Ð&¨9Ð&Ø�IŠI�e˜B”iÑ Ô Ð Ð Ø�2�A�2ŒY˜9 kÐ2Ò2Ð2µs¸5±z´zÀA²~°~Ý˜˜qœ‘]”]ˆFøÝ˜uÒ$Ð$ÝÐ3Ñ4Ô4Ð4Ø€~Ý”�CÐGÐGÀÐGÑGÔGÑGÔGÈ1ÑLÈqÑPÑQÔQÐTUÑUˆÝ$ V­eµYÅ
Ð-KÑLÔLÐm�3ˆv‰;Œ;ˆ;ÕRVÐW]ÑR^ÔR^×RcÒRcÑReÔReÔRm€DØ¨%¸fÐSWÐXÐXÐXr"   g®Gáz®ï?)r   Úpointsútorch.TensorÚcolorsÚscaleúfloat | Noner   Úfloatc          
     ó®  — ddl m} | j        t          | ¦  «        }}|�€€|dk     rt	          d¦  «        ‚t          | t          j        ¦  «        } ||¦  «                             |t          d|¦  «        d¬¦  «        \  }}	t          j
        |dd…d	d…f         dz                       d	¦  «        ¦  «        }
t          j        |
d
t          j                             |                     d¦  «        | 	                    d¦  «        z
  ¦  «        z  ¦  «        }
t          j        |
t          j        |
d¦  «        ¦  «        }
t%          j        t          j        |
dd…df         dd	¦  «                             t          j        ¦  «        ¦  «                             |¦  «        }n1t%          j        |dft3          |¦  «        t$          j        |¬¦  «        }t%          j        |dt$          j        |¬¦  «        }d	|dd…df<   |                      ¦   «         ||t%          j        |f|t$          j        |¬¦  «        |                     ¦   «         dz
  t6          z  ddg dœS )aå  Splat dict of small isotropic Gaussians for a point cloud: colors [N, 3] in 0..1 (sRGB) become sh_dc (degree 0),
    rotations identity, opacity `opacity`. scale None estimates each point's scale as the 3DGS initialisation does: the
    root mean square distance to its 3 nearest neighbours (k-d tree on the CPU), at least 1e-4 of the bounding box
    diagonal and at most the 98th percentile of these distances; otherwise every point gets `scale`. Tensors are on the device of points.r   )ÚcKDTreeNrE   z1Estimating splat scales needs at least two pointsé   r   )ÚkÚworkersr   g-Cëâ6?éb   rD   )r   r   g      à?r§   )Úscipy.spatialrë   r   rn   r,   r!   r   rj   ÚqueryÚminÚsqrtÚmeanrv   r¯   r°   rÌ   ÚminimumÚ
percentiler   r£   Úrepeatr   ro   r   Úfullré   rm   ÚSH_C0)rä   ræ   rç   r   rë   r   r·   ÚarrayÚ	distancesrÁ   Úsigmar~   r   s                r    Úpoints_to_splatsrý   ª   s#  € ð
 &Ð%Ð%Ð%Ð%Ð%Ø”M¥3 v¡;¤;ˆE€FØ�}Ø�1Š9ˆ9ÝÐPÑQÔQÐQÝ�v�rœzÑ*Ô*ˆØ�w˜u‘~”~×+Ò+¨EµS¸¸E±]´]ÈBÐ+ÑOÔO‰ˆ	�1Ý”˜ 1 1 1 a b b 5Ô)¨QÑ.×4Ò4°QÑ7Ô7Ñ8Ô8ˆÝ”
˜5 $­¬¯ª¸¿	º	À!¹¼ÀuÇyÂyÐQRÁ|Ä|Ñ8SÑ)TÔ)TÑ"TÑUÔUˆÝ”
˜5¥"¤-°°rÑ":Ô":Ñ;Ô;ˆÝÔ!¥"¤)¨E°!°!°!°T°'¬N¸A¸qÑ"AÔ"A×"HÒ"HÍÌÑ"TÔ"TÑUÔU×XÒXÐY_Ñ`Ô`ˆˆå”˜U A˜J­¨e©¬½E¼MÐRXÐYÑYÔYˆÝ”˜E 1­E¬MÀ&ÐIÑIÔI€IØ€Iˆaˆaˆa�ˆd�OØ—\’\‘^”^¨vÀIÕ\aÔ\fÐhmÐgoÐqxõ  AFô  ANð  W]ð  ]^ñ  ]^ô  ]^Ø—l’l‘n”n sÑ*­eÑ3ÀÐSTÐbdðfð fð fr"   r¹   c           
     ó˜  — | d                               d¦  «        \  }}}}t          | | d         | d                              g d¢¦  «        z  t          j        | || |gd¦  «        ¬¦  «        }| d         �R| d                              t
          d| d         j        d         …         ¦  «        }| d         |ddd…df         z  |d<   |S )zÛSplats converted from OpenCV axes (+X right, +Y down, +Z forward) to the glTF axes of the 3D gallery (+Y up,
    +Z towards the viewer): a 180 degree turn about X applied to means, rotations and SH coefficients (exact).r   r   r}   )g      ð?ç      ð¿rÿ   )r}   r   r‚   N)Úunbindr‹   Ú
new_tensorr   r™   Ú_SH_FLIP_SIGNSrr   )r¹   ÚwrG   rH   rI   Ú	convertedÚsignss          r    Úsplats_opencv_to_gltfr  Â   s
  € ð ˜Ô$×+Ò+¨AÑ.Ô.�J€A€qˆ!ˆQÝ�V 6¨'¤?°V¸G´_×5OÒ5OÐPaÐPaÐPaÑ5bÔ5bÑ#bÕnsÔnyÐ|}Ð{}ð  @Að  DEð  CEð  GHð  {Ið  KLñ  oMô  oMð  Nñ  Nô  N€IØˆiÔÐ$Ø�yÔ!×,Ò,­^Ð<W¸VÀIÔ=NÔ=TÐUVÔ=WÐ<WÔ-XÑYÔYˆØ% iÔ0°5¸¸q¸q¸qÀ$¸Ô3GÑGˆ	�)ÑØÐr"   c           
     ó~  — t          | ¦  «        t          j        t          j        t          |¦  «        dd¦  «        dz  ¦  «                             t          j        ¦  «        }} t          j        t          | ¦  «        t          j        g d¢¦  «        ¦  «        }t          d¦  «        D ]\  }}| dd…|f         ||<   Œt          d¦  «        D ]\  }}|dd…|f         ||<   Œdd	d
t          | ¦  «        › �dddddddg
}d 
                    |¦  «        dz                        d¦  «        |                     ¦   «         z   S )zjStandard point-cloud PLY (binary little-endian): float x y z and uchar red green blue from colors in 0..1.r   r   éÿ   ))rG   rg   )rH   rg   )rI   rg   )ÚredÚu1)Úgreenr
  )Úbluer
  ÚxyzN)r	  r  r  r[   r\   rb   zproperty float xzproperty float yzproperty float zzproperty uchar redzproperty uchar greenzproperty uchar bluerf   rX   r‘   )r!   r   Úrintri   r   Úuint8Úemptyrn   r   rÍ   rz   r{   r|   )rä   ræ   ÚrecordsrQ   r¥   Úchannelr‰   s          r    Úwrite_points_plyr  Í   sV  € å˜F‘^”^¥R¤W­R¬WµV¸F±^´^ÀQÈÑ-JÔ-JÈSÑ-PÑ%QÔ%Q×%XÒ%XÕY[ÔYaÑ%bÔ%bˆF€FÝŒh•s˜6‘{”{¥B¤Hð  .Hð  .Hð  .Hñ  %Iô  %Iñ  Jô  J€GÝ˜UÑ#Ô#ð %ð %‰ˆˆ4Ø˜q˜q˜q !˜tœˆ�‰ˆÝÐ 8Ñ9Ô9ð (ð (‰
ˆˆ7Ø! ! ! ! Q $œ<ˆ�ÑÐØÐ6Ð8WÍ#ÈfÉ+Ì+Ð8WÐ8WÐYkÐmð  BTØ"Ð$:Ð<QÐS_ða€Fà�IŠI�fÑÔ Ñ$×,Ò,¨WÑ5Ô5¸¿ºÑ8IÔ8IÑIÐIr"   )r   r   )r#   r$   r   r%   )r   r$   )Nr=   )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‹   )Ú__doc__Ú
__future__r   rp   Úpathlibr   r   r   r   Úformatsr   r   r   rù   r«   rl   r  ro   r!   r2   r<   rŠ   rº   rÂ   rÐ   rÙ   rã   rý   r  r  r=   r"   r    ú<module>r     sâ  ððð ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ð Ð à Ð Ð Ð Ø €€€à DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ Dà€Ø<Ð<Ð<Ð ØÐ àFÐFÐF€ð œ
ð Nð Nð Nð Nð Nð:ð :ð :ð :ðð ð ð ðGð Gð Gð Gð Gð, %*ð ð ð ð ð ð ð6Gð Gð Gð GðIð Ið Ið Ið%ð %ð %ð %ð Yð Yð Yð Yð.fÐquð fð fð fð fð fð fð0ð ð ð ð
Jð 
Jð 
Jð 
Jð 
Jð 
Jr"   