§
    IŒájÿT  ã                   ó˜  — d Z ddlZddlZddlZddlZddlmZ ddlZej	         
                    d e ee¦  «        j        ¦  «        ¦  «         ddlmZmZmZ d„ dD ¦   «         Zg d¢Zg d¢Zd	„ Zd
„ Zd„ Zd„ Zd„ ZdZedk    rF e¦   «         Zedz                        ee¦  «        ¦  «          e ee¦  «        dedz  ¦  «         dS dS )a]  The synthesis page: ../report/synthesis.html, from ../report/ablation.csv (ablation.py) and the gallery (gallery.py).
The inventory and the conclusions are written below (INVENTORY, the text in page()); every number comes from the CSV.

    env -u PYTHONPATH PYTHONWARNINGS=ignore .venv/bin/python ~/code/data/meshes/fcp_2710_tests/scripts/synth.py
é    N)ÚPath)ÚCSSÚOBJÚREPORTc                 ó    — g | ]}d D ]}||f‘ŒŒS ))	ÚcleanÚnoise0p2Únoise0p6Únoise1Úpn0p12Úpn0p6Úpn1p2ÚdgradÚdstripe© )Ú.0ÚnÚts      ú;/home/joao/code/data/meshes/fcp_2710_tests/scripts/synth.pyú
<listcomp>r      sH   € ð 
Jð 
Jð 
J�Qð 6Ið 
Jð 
J°ˆ1ˆaˆ&ð 
Jð 
Jð 
Jð 
Jó    )Ú10000Ú2048)ÚpackageÚ	pointtestÚAzA+pointtestÚhybridzhybrid+pointtestzhybrid-gatedzhybrid-gated+pointtestÚthinwallzthinwall+pointtestÚepsÚlocalÚgwnzgwn+pointtest))ÚorientationzNrobust plane directions + spanning-tree patches + leak-proof flood vote (surf)z'docs/pointcloud-slicer.md, DECISIONS 25z1per-point normals and signs without given normalsu;   10k Chamfer/mesh 6.1 â†’ 1.6, 2048 13.9 â†’ 4.9 (9 objects)zin the package (v5.2)zrings: the basis of everything)r"   z:3D flood alone; winding-number vote; sign-consistency passz$pointcloud-slicer.md; pc_progress.pyzglobal inside/outsideuc   flood 53â€“64 % right alone; winding worse (bowl 15.9, mug 34.7Ã—); consistency mug 40 â†’ 45 wrongzrejected (flood kept as a vote)õ   â€”)úfield / topologyzband slicer (dilate, fill)z#fousd-3d README, ShapeNet diagnosiszrobust under noiseuk   lids on bowl/mug/wine glass; 17 of 20 worst ShapeNet objects; at 0.6 % noise 17â€“18 parts (surf 406â€“452)z&kept for noisy clouds and registrationz$parts few, rings wrong on thin walls)r$   zJsigned slicer + MST orientation, 5 % fallback to band; ADAPT local spacingzovernight LOG, t3_pcpnet LOGz.signed pixels; local reach on variable densityuD   slice IoU 0.904 â†’ 0.954; variable density parts 642 â†’ 24 (ADAPT)z1superseded by surf (ADAPT has no surf equivalent)z2parts: ADAPT is the only density fix ever measured)r$   zARIMLS within 1.25 spacings, flood beyond, marching squares (surf)zDECISIONS 25z'the implicit surface read at the layersu?   the 10k / 2048 gains above; noise: 452â€“831 parts at 0.6â€“2 %z4default; fails on noise and density (surf_issues.md)z)rings ragged (hooks); thin walls fragment)r$   u8   surf constants Ã— f with the minimum loop Ã— fÂ² (noise)zHANDOVER_surf_noise_v52.mdzwider support for noisy cloudsu[   100k 0.6 %: 406 â†’ 13 parts (f = 6); but deletes limbs, and clean sparse clouds want f = 1u2   open: scale by an estimated Ïƒ, not by the spacingu2   parts â†“â†“ under noise, rings lose thin features)r$   z<Poisson; rolling ball / alpha shape; shrink-wrap; 2D balloonz pointcloud-slicer.md; MORNING.mdzother surfacesz`Poisson val 0.0213 vs 0.0126, not watertight on 41 %; ball slips or bridges; wrap fixes topologyÚrejectedr#   )r$   zthin-wall vote / centroid rulezovernight exp_04, exp_16zopen walls under 2 spacingsu:   62 of 211 objects worse / walls open but 7â€“10 hole partsr%   u	   parts â†‘)r$   z2B: contours from the points' own sheets (no field)ú this session, scripts/ringfit.pyz0topology from a neighbour graph split by normalsuE   3â€“10Ã— the package's error: lost layers, wild loops, open crescentszIrejected as built; its face separation by normals is kept (in the hybrid)r#   )úring geometryz8refit rings to the points (harmonics by held-out layers)zpointcloud-slicer.md (refit.py)zpositions onlyz:fixes positions where the start is right; diverges at gapsz)rejected then ('rings are not the place')u   rings âœ“, topology âœ—)r'   zeA: slicer rings refitted to their own points, N from the point count, plane-corrected slab, loops cutr&   zremoves hooks / extra lengthzsee the ablation: Aú	see belowu	   rings âœ“)r'   zfewer harmonics Nz'noisy_clouds.md; this session (N sweep)zregularise by truncationzOno change in parts at 10k or 200k (the wobble is sample sliding, all harmonics)r%   r#   )r'   u7   decode â†’ keep N' harmonics â†’ re-encode (refit pass)u   noisy_clouds.md Â§4zdenoise by a second passu:   mesh noise: bowl 0.171 â†’ 0.085 (0.6 %), parts 101 â†’ 81z*works on mesh noise; never tried on cloudsu   rings âœ“, parts â†“)úlayer consistencyz5surf-n / surf-rn (drop one-layer pieces, bridge gaps)zpc_progress.py; surf.pyz$neighbour-layer consistency on ringsz=no gain at any window (IoU 0.889/0.888/0.887); parts = surf-rzHoff (and the noise comparison was invalid: flags never reached the code)r#   )r)   z?neighbour sweeps: rings started from the next layer and refinedz"this session, scripts/neighbour.pyz(carry a good ring through a broken layerzNhelps thick organic shapes, hurts thin walls (mixing refined and slicer rings)zsuperseded by the hybridu   parts Â±)r)   zahybrid: S (A) by default, U/D carried sets replace a whole layer if they pass; trusted rings keptzthis session, scripts/hybrid.pyz1repair C-rings and fragments from good neighbourszsee the ablation: hybridr(   u"   rings âœ“, parts â†“ on thin walls)r)   z^hybrid-gated: carried sets only on suspicious layers (untrusted ring or a sliver < 3 spacings)zthis sessionztouch only broken layerszsee the ablation: hybrid-gatedr(   zas hybrid, safer elsewhere)úparts / cutsz=tracked-fit with fit_tol = 0.01 (mesh) / one spacing (clouds)zDECISIONS 22, 25zcut where one height fit missesu+   horse 10k 28 â†’ 17, scans median 58 â†’ 47zin the packageÚparts)r*   z^point test: cut only where the fitted ring fails to explain the points (two-sided, 2 spacings)z!this session, scripts/pointfit.pyz(judge cuts on geometry, not coefficientsu/   dino 200k 40 â†’ 28 (mesh 25); see the ablationr(   u	   parts â†“)r*   zVfit_tol up to 10; MIN_PIECE; continue-jumps; drop_fragments; keep largest solid + holez&noisy_clouds.md; consolidation RESULTSzother cut / merge rulesui   noisy bowl 831 â†’ 805 parts (97 % from tracking); drop_fragments âˆ’37 parts for +8â€“17 % Chamfer; lidsuA   rejected (continue-jumps: better Chamfer, 5Ã— slower, superseded)zparts vs accuracy)ÚnoiseuX   speck removal (ring area < 4Ï€ sÂ²), Ïƒ-scaled thresholds, routing to band by estimatorszsurf_issues.mdz6kill specks and bubbles under noise / variable densityz1estimators catch 69 of 71 exploding PCPNet cloudszproposed, not builtu   parts â†“â†“ under noise)r,   z!stop at the energy knee (~99.5 %)u   noisy_clouds.md Â§3zdenoising by truncationzbest Chamfer past the kneezrule not yet chosenr#   c                  ó(  — t           dz                       ¦   «         5 } d„ t          j        | ¦  «        D ¦   «         }d d d ¦  «         n# 1 swxY w Y   |D ]<}dD ]}t	          ||         ¦  «        ||<   ŒdD ]}t          ||         ¦  «        ||<   ŒŒ=|S )Nzablation.csvc                 ó0   — g | ]}|d          t           v ¯|‘ŒS )Úobject)r   ©r   Úrs     r   r   zload.<locals>.<listcomp>Z   s&   € ÐCÐCÐC�a°°(´½sÐ0BÐ0B�Ð0BÐ0BÐ0Br   )r+   ÚholesÚshortÚ	ref_partsÚempty)ÚmeanÚp95Úseconds)r   ÚopenÚcsvÚ
DictReaderÚintÚfloat)ÚfÚrowsr1   Úks       r   ÚloadrA   X   sù   € Ý
�>Ñ
!×	'Ò	'Ñ	)Ô	)ð D¨QØCÐC�3œ>¨!Ñ,Ô,ÐCÑCÔCˆðDð Dð Dñ Dô Dð Dð Dð Dð Dð Dð Døøøð Dð Dð Dð Dàð ð ˆØBð 	ð 	ˆAÝ�q˜”t‘9”9ˆAˆa‰DˆDØ+ð 	ð 	ˆAÝ˜˜1œ‘;”;ˆAˆa‰DˆDð	à€Ks   �AÁAÁAc                 ó€  ‡‡‡‡	— g }t           D �].\  Š	Šˆˆ	fd„| D ¦   «         }|sŒd„ |D ¦   «         Št          D �]Šˆfd„|D ¦   «         }|sŒt          j        d„ |D ¦   «         ¦  «        }t          j        ˆfd„|D ¦   «         ¦  «        }|                     t          ‰	› d‰› �‰t          |¦  «        t          t          j        |¦  «        ¦  «        t          t          j
        t          j        |dz
  ¦  «        dk    ¦  «        ¦  «        t          t          d	„ |D ¦   «         ¦  «        ¦  «        t          t          d
„ |D ¦   «         ¦  «        ¦  «        t          |¦  «        r!t          t          j        |¦  «        ¦  «        nt          d¦  «        t          t          j
        |dk     ¦  «        ¦  «        t          t          j
        |dk    ¦  «        ¦  «        t          t          d„ |D ¦   «         ¦  «        ¦  «        t          t          j        d„ |D ¦   «         ¦  «        ¦  «        ¬¦  «        ¦  «         �Œ�Œ0|S )zWPer cloud type and configuration: parts against the mesh and error against the package.c                 óD   •— g | ]}|d          ‰k    ¯|d         ‰k    ¯|‘ŒS ©ÚcloudÚpointsr   ©r   r1   r   Útags     €€r   r   zsummary.<locals>.<listcomp>g   s5   ø€ ÐIÐIÐI�Q ! G¤*°Ò"3Ð"3¸¸(¼ÀqÒ8HÐ8HˆqÐ8HÐ8HÐ8Hr   c                 ó8   — i | ]}|d          dk    ¯|d         |“ŒS )Úconfigr   r/   r   r0   s     r   ú
<dictcomp>zsummary.<locals>.<dictcomp>j   s,   € ÐHÐHÐH 1¨q°¬{¸iÒ/GÐ/G��(”˜QÐ/GÐ/GÐ/Gr   c                 óD   •— g | ]}|d          ‰k    ¯|d         dk    ¯|‘ŒS )rJ   r+   r   r   )r   r1   Úcfgs     €r   r   zsummary.<locals>.<listcomp>l   s0   ø€ ÐKÐKÐK˜ A h¤K°3Ò$6Ð$6¸1¸W¼:Èº?¸?�!¸?¸?¸?r   c                 óL   — g | ]!}|d          t          |d         d¦  «        z  ‘Œ"S )r+   r4   é   )Úmaxr0   s     r   r   zsummary.<locals>.<listcomp>o   s/   € ÐNÐNÐNÀa˜a œj­3¨q°¬~¸qÑ+AÔ+AÑAÐNÐNÐNr   c                 ó’   •— g | ]C}|d          ‰v ¯t          j        |d         ¦  «        ¯&|d         ‰|d                   d         z  ‘ŒDS )r/   r6   ©ÚnpÚisfinite)r   r1   Úbases     €r   r   zsummary.<locals>.<listcomp>p   sc   ø€ ð  Að  Að  AÀaÐQRÐS[ÔQ\Ð`dÐQdÐQdÕikÔitÐuvÐw}Ôu~ÑiÔiÐQd˜A˜fœI¨¨Q¨x¬[Ô(9¸&Ô(AÑAÐQdÐQdÐQdr   ú rO   g      Ð?c              3   ó&   K  — | ]}|d          V — ŒdS ©r+   Nr   r0   s     r   ú	<genexpr>zsummary.<locals>.<genexpr>r   s*   è è € ÐXpÐXpÐhiÐYZÐ[bÔYcÐXpÐXpÐXpÐXpÐXpÐXpr   c              3   ó&   K  — | ]}|d          V — ŒdS )r4   Nr   r0   s     r   rY   zsummary.<locals>.<genexpr>s   s&   è è € Ð'CÐ'C¸1¨¨+¬Ð'CÐ'CÐ'CÐ'CÐ'CÐ'Cr   Únangffffffî?gÍÌÌÌÌÌð?c              3   ó&   K  — | ]}|d          V — ŒdS )r5   Nr   r0   s     r   rY   zsummary.<locals>.<genexpr>u   s&   è è € Ð)AÐ)A¸¨!¨G¬*Ð)AÐ)AÐ)AÐ)AÐ)AÐ)Ar   c                 ó   — g | ]
}|d          ‘ŒS )r8   r   r0   s     r   r   zsummary.<locals>.<listcomp>u   s    € ÐXrÐXrÐXrÐjkÐYZÐ[dÔYeÐXrÐXrÐXrr   )rE   rM   r   Úparts_ratioÚwithinr+   ÚrefÚerrÚbetterÚworser5   Úsec)ÚCLOUDSÚCFGSrS   ÚarrayÚappendÚdictÚlenr=   Úmedianr<   ÚsumÚabs)
r?   ÚoutÚsubÚrsÚratiora   rU   rM   r   rH   s
         @@@@r   Úsummaryrr   c   su  øøøø€ à
€CÝð wñ w‰ˆˆQØIÐIÐIÐIÐI˜$ÐIÑIÔIˆØð 	ØØHÐH¨ÐHÑHÔHˆÝð 
	wñ 
	wˆCØKÐKÐKÐK˜SÐKÑKÔKˆBØð ØÝ”HÐNÐNÈ2ÐNÑNÔNÑOÔOˆEÝ”(ð  Að  Að  Að  AÈ2ð  Añ  Aô  Añ  Bô  BˆCØ�JŠJ•t S , ,¨1 , ,°C½3¸r¹7¼7ÕPUÕVXÔV_Ð`eÑVfÔVfÑPgÔPgÝ#&¥r¤v­b¬f°U¸Q±YÑ.?Ô.?À4Ò.GÑ'HÔ'HÑ#IÔ#IÕQTÕUXÐXpÐXpÐmoÐXpÑXpÔXpÑUpÔUpÑQqÔQqÝ #¥CÐ'CÐ'CÀÐ'CÑ'CÔ'CÑ$CÔ$CÑ DÔ DÕcfÐgjÑckÔckÐJ}Í%ÕPRÔPYÐZ]ÑP^ÔP^ÑJ_ÔJ_ÐJ_ÕqvÐw|Ñq}Ôq}Ý#&¥r¤v¨c°DªjÑ'9Ô'9Ñ#:Ô#:Å#ÅbÄfÈSÐSWÊZÑFXÔFXÑBYÔBYÝ"%¥cÐ)AÐ)A¸bÐ)AÑ)AÔ)AÑ&AÔ&AÑ"BÔ"BÍÍbÌiÐXrÐXrÐoqÐXrÑXrÔXrÑNsÔNsÑHtÔHtð	vñ vô vñ wô wð wñ wñ
	wð €Jr   c                 óŽ  — d}g d }}| D ]¢}|d         |k    rdnd}|d         }|                      d|› d|d         › d|d         › d|d	         › d
|d         › d|d         d›d|d         › d|d         › d|d         d›d|d         › d
|d         › d|d         › d|d         d›d�¦  «         Œ£d|› d                     |¦  «        › d�S )Nu  <tr><th>cloud</th><th>configuration</th><th>parts (all objects) / mesh</th><th>median parts Ã· mesh</th><th>objects within Â±25 % of the mesh's parts</th><th>median error Ã· package</th><th>error better / worse (Â±5 %)</th><th>empty decodes</th><th>median encode s</th></tr>rE   z" style='border-top:2px solid #999'Ú z<trz><td>ú	</td><td>rM   r+   z / r`   r^   ú.2fr_   z of r   ra   z.3frb   rc   r5   rd   z.1fú
</td></tr>z<table>ú</table>)rh   Újoin)ÚSÚheadÚbodyÚlastÚsÚseps         r   Úfmt_summaryr€   y   s”  € ðB€Dð �Tˆ$€DØð oð oˆØ67¸´jÀDÒ6HÐ6HÐ2Ð2ÈbˆØ�ŒzˆØ�Šð n˜#ð nð n A g¤Jð nð n¸¸5¼ð nð nÈAÈgÌJð nð nÐ[\Ð]bÔ[cð nð nØ˜]Ô+Ðoðnð nØ:;¸H¼+ðnð nØKLÈSÌ6ðnð nØ\]Ð^cÔ\dÐoðnð nà˜Xœ;ðnð nà+,¨W¬:ðnð nà@AÀ'Ä
ðnð nàUVÐW\ÔU]Ðmðnð nð nñ 	oô 	oð 	oð 	oð 3�TÐ2˜2Ÿ7š7 4™=œ=Ð2Ð2Ð2Ð2r   c                 óè  ‡‡‡‡‡— ˆˆfd„| D ¦   «         }|sdS dd                      d„ t          D ¦   «         ¦  «        z   dz   }g }t          D �]…Šˆfd„|D ¦   «         Š‰sŒt          t	          ‰                     ¦   «         ¦  «        ¦  «        d         Šˆfd„t          D ¦   «         }|rt          ˆfd	„|D ¦   «         ¦  «        nd }t          ˆˆfd
„|D ¦   «         d ¬¦  «        }g }	t          D ]±}
|
‰vr|	                     d¦  «         Œ‰|
         }t          j	        |d         ¦  «        rd|d         z  d›nd}t          |d         ‰z
  ¦  «        |k    rdnd}|�|d         |k    rdnd}|	                     d|› |d         › |rdnd› d|› |› |rdnd› d�	¦  «         Œ²|                     d‰› d‰› dd                      |	¦  «        › d�¦  «         �Œ‡d‰› d‰› d|› d                      |¦  «        › d�S )Nc                 óD   •— g | ]}|d          ‰k    ¯|d         ‰k    ¯|‘ŒS rD   r   rG   s     €€r   r   zper_object.<locals>.<listcomp>ˆ   s5   ø€ Ð
EÐ
EÐ
E�˜a œj¨CÒ/Ð/°A°h´KÀ1Ò4DÐ4Dˆ1Ð4DÐ4DÐ4Dr   rt   z&<tr><th>object</th><th>mesh parts</th>c              3   ó"   K  — | ]
}d |› d�V — ŒdS )z<th>z</th>Nr   )r   Úcs     r   rY   zper_object.<locals>.<genexpr>‹   s+   è è € Ð=\Ð=\ÐRS¸oÀQ¸o¸o¸oÐ=\Ð=\Ð=\Ð=\Ð=\Ð=\r   z</tr>c                 ó:   •— i | ]}|d          ‰k    ¯|d         |“ŒS )r/   rJ   r   )r   r1   Únames     €r   rK   zper_object.<locals>.<dictcomp>Ž   s-   ø€ ÐAÐAÐA ¨Q¨x¬[¸DÒ-@Ð-@ˆa�Œk˜1Ð-@Ð-@Ð-@r   r4   c                 ó\   •— g | ](}|‰v ¯t          j        ‰|         d          ¦  «        ¯&|‘Œ)S )r6   rR   ©r   r„   rp   s     €r   r   zper_object.<locals>.<listcomp>’   s4   ø€ ÐHÐHÐH�A  b  ­R¬[¸¸A¼¸v¼Ñ-GÔ-G ˆa   r   c              3   ó4   •K  — | ]}‰|         d          V — ŒdS )r6   Nr   rˆ   s     €r   rY   zper_object.<locals>.<genexpr>“   s+   øè è € Ð/Ð/ q�R˜”U˜6”]Ð/Ð/Ð/Ð/Ð/Ð/r   c              3   óT   •K  — | ]"}t          ‰|         d          ‰z
  ¦  «        V — Œ#dS rX   )rm   )r   r„   r`   rp   s     €€r   rY   zper_object.<locals>.<genexpr>”   s8   øè è € Ð<Ð<°A•c˜"˜Qœ% œ.¨3Ñ.Ñ/Ô/Ð<Ð<Ð<Ð<Ð<Ð<r   )Údefaultz	<td></td>r6   g     @�@rv   r5   r+   z<b>z<td>z</b>õ    Â· z</td>ú<tr><td>ru   z<h3>z points</h3><table>rx   )ry   rf   r   ÚnextÚiterÚvaluesÚminrh   rS   rT   rm   )r?   rH   r   ro   r{   r|   ÚokÚbest_eÚbest_pÚcellsr„   r1   ÚeÚpbÚebr†   r`   rp   s    ``            @@@r   Ú
per_objectr™   ‡   s‘  øøøøø€ Ø
EÐ
EÐ
EÐ
EÐ
E�dÐ
EÑ
EÔ
E€CØð ØˆrØ3°b·g²gÐ=\Ð=\ÕW[Ð=\Ñ=\Ô=\Ñ6\Ô6\Ñ\Ð_fÑf€DØ€DÝð Oñ OˆØAÐAÐAÐA cÐAÑAÔAˆØð 	ØÝ•4˜Ÿ	š	™œÑ$Ô$Ñ%Ô% kÔ2ˆØHÐHÐHÐH�ÐHÑHÔHˆØ35Ð?•Ð/Ð/Ð/Ð/¨BÐ/Ñ/Ô/Ñ/Ô/Ð/¸4ˆÝÐ<Ð<Ð<Ð<Ð<¸Ð<Ñ<Ô<ÀdÐKÑKÔKˆØˆÝð 	nð 	nˆAØ˜ˆ{ˆ{Ø—’˜[Ñ)Ô)Ð)ØØ�1”ˆAÝ,.¬K¸¸&¼	Ñ,BÔ,BÐO�3˜˜6œ‘?Ð(Ð(Ð(ÈˆAÝ˜a œj¨3Ñ.Ñ/Ô/°6Ò9Ð9��¸rˆBØ Ð,°°6´¸fÒ1DÐ1D��È"ˆBØ�LŠLÐl Ðl A g¤JÐl¸"Ð0D°°À"ÐlÐlÈ"ÐlÈaÐlÐ[]ÐQeÐQWÐQWÐceÐlÐlÐlÑmÔmÐmÐmØ�ŠÐM˜tÐMÐM¨cÐMÐM¸¿ºÀ¹¼ÐMÐMÐMÑNÔNÐNÑNØN�#ÐNÐN˜1ÐNÐN°ÐN°r·w²w¸t±}´}ÐNÐNÐNÐNr   c                 ó"  ‡ — t          ‰ ¦  «        }d                     d„ t          D ¦   «         ¦  «        }d                     d„ t          dz  dz                       ¦   «         rdndt          dz  dz                       ¦   «         rd	ndfD ¦   «         ¦  «        }d                     ˆ fd
„t
          D ¦   «         ¦  «        }dt          › dt          j        d¦  «        › dt          ‰ ¦  «        › d|pd› dt          › dt          |¦  «        › d|› d|› d�S )Nrt   c              3   óR  K  — | ]¢\  }}}}}}}d t          j        |¦  «        › dt          j        |¦  «        › dt          j        |¦  «        › dt          j        |¦  «        › dt          j        |¦  «        › dt          j        |¦  «        › dt          j        |¦  «        › d�V — Œ£dS )r�   ru   rw   N)ÚhtmlÚescape)r   ÚaÚbr„   Údr–   r>   Úgs           r   rY   zpage.<locals>.<genexpr>¥   sþ   è è € ð Lð LÙj}ÐjkÐmnÐpqÐstÐvwÐyzÐ|}ðf�Tœ[¨™^œ^ð fð fµd´kÀ!±n´nð fð fÍtÌ{Ð[\É~Ì~ð fð fÕhlÔhsÐtuÑhvÔhvð fð fÝœ Q™œðfð fÝ26´+¸a±.´.ðfð fÝKOÌ;ÐWXÉ>Ì>ðfð fð fð Lð Lð Lð Lð Lð Lr   rŒ   c              3   ó   K  — | ]}|¯|V — Œ	d S ©Nr   )r   Úxs     r   rY   zpage.<locals>.<genexpr>§   sG   è è € ð Eð E˜Að CDðE�að Eð Eð Eð Eð Eð Er   Úgallery_finalz
index.htmlz\<a href='gallery_final/index.html'><b>final gallery: package, point test, eps, local</b></a>Úgalleryz;<a href='gallery/index.html'>full gallery: every method</a>c              3   ó@   •K  — | ]\  }}t          ‰||¦  «        V — Œd S r£   )r™   )r   r   r   r?   s      €r   rY   zpage.<locals>.<genexpr>ª   s3   øè è € Ð=Ð=©d¨a°•:˜d A qÑ)Ô)Ð=Ð=Ð=Ð=Ð=Ð=r   z´<!doctype html><html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1"><title>Point-cloud slicing: synthesis</title>
<style>u   td,th{font-size:12.5px} .box{border-left:4px solid #2f6f8f;padding:6px 12px;background:#f1efe9;margin:10px 0}</style></head><body>
<p><a href="index.html">â†� report</a></p>
<h1>Point-cloud slicing: what each approach is good for, and what to combine</h1>
<p class="mut">z%Y-%m-%d %H:%Muƒ    Â· fcp v5.2 (CUDA) Â· bench prototypes in <code>scripts/</code> (package untouched) Â·
numbers: <code>report/ablation.csv</code> (uƒ    rows), built by <code>scripts/ablation.py</code> and <code>scripts/synth.py</code> Â·
gallery (parts and slices of every object): znot built yetz.</p>
uw
  
<h2>1. Test set</h2>
<p>10 watertight meshes, upright on +z (<code>parts_report.OBJ</code>): battery (synthetic stepped box), dress (solid envelope), elephant,
two bowls (ObjectFolder, GSO), mug, dino, shoe, loaf pan (thin steel walls), horse. Noisy meshes (<a href="noisy.html">noisy.html</a>):
a smooth one-to-one 3D displacement field, Ïƒ = 0.2 / 0.6 / 1 % of the diagonal along the normal, topology kept (no face turned over,
no self-crossing section); the loaf pan's source is full of slivers, so its 0.6 / 1 % versions reach only 0.21 / 0.27 %. Clouds:
10 000 and 2 048 points (seeded): area-uniform from the clean and from each noisy mesh; per-point Gaussian noise of 0.12 / 0.6 /
1.2 % of the diagonal on clean samples (PCPNet's protocol, tags pn*); variable density on the clean mesh (dgrad: kept with
probability falling 10:1 along x; dstripe: stripes along y kept with probability 1 and 0.2): 180 clouds. The mesh route's parts on the mesh the
cloud came from are the parts reference; errors are against the clean mesh (mean of the symmetric nearest-point distance, 50k samples
per side, over the diagonal). 128 layers, 1024 atoms, up = +z.</p>
<h2>2. Configurations</h2>
<ul>
<li><b>package</b>: <code>fcp.encode</code> (surf slicer, tracked-fit, fit_tol "auto").</li>
<li><b>pointtest</b>: the package's slices; a track is cut only where one height fit fails to explain the layer's points (two-sided,
2 spacings, p95) (<code>pointfit.py</code>).</li>
<li><b>A</b>: the slicer's rings refitted to their own points (slab within a spacing, moved onto the plane along the surface; points by
face from the normals; N from the point count; self-loops cut) (<code>ringfit.py</code>).</li>
<li><b>hybrid</b>: A by default; on every layer the contours of the layer below (U) and above (D), carried and refitted, replace the
whole layer when they are backed by points, fit them, explain as many points, fill nothing new and keep every trusted slicer ring
(<code>hybrid.py</code>). <b>hybrid-gated</b>: U/D only where the slicer's layer is suspicious (an untrusted ring, or a solid sliver
under 3 spacings wide).</li>
<li>"+pointtest": the same slices, cut by the point test.</li>
<li><b>thinwall</b>: thin walls (a parallel face 0.4â€“1.5 spacings along the normal) added to the slicer's field as a band
(<code>thinwall.py</code>).</li>
<li><b>eps</b>: one scale Îµ = max(spacing, 4Ïƒ), Ïƒ the cloud's per-point noise given to the encoder (0 for clean, mesh-noise and
density clouds): the slicer's support, band and inlier distance Ã— Îµ/spacing, the minimum loop Ã— (Îµ/spacing)Â², cuts by the point test
(<code>eps.py</code>).</li>
</ul>
<h2>3. Summary per cloud type</h2>
u‹   
<h2>4. Per object</h2>
<p class="mut">parts Â· mean error Ã—10â�»Â³ of the diagonal. Bold: parts closest to the mesh's, lowest error.</p>
aM  
<h2>5. Inventory of approaches</h2>
<p class="mut">From <code>docs/pointcloud-slicer.md</code>, <code>docs/surf_issues.md</code>, <code>docs/noisy_clouds.md</code>,
<code>docs/HANDOVER_surf_noise_v52.md</code>, <code>docs/consolidation/RESULTS.md</code>, <code>api/DECISIONS.md</code> 22 / 25,
<code>api/OPEN.md</code> 9, the research repository (fousd-3d: overnight logs, ShapeNet diagnosis, pc-slicer prototypes) and this
session's prototypes.</p>
<table><tr><th>stage</th><th>approach</th><th>source</th><th>what it does</th><th>evidence</th><th>verdict</th><th>rings / parts</th></tr>u  </table>
<h2>6. This session's pages</h2>
<p><a href="index.html">parts at 200k</a> Â· <a href="parts_clean_10000.html">parts at 10k (all prototypes)</a> Â·
<a href="splits_dino.html">the dino's cuts</a> Â· <a href="analysis_ringfit.html">A vs B</a> Â· <a href="middle_clean_10000.html">middle slices</a> Â·
<a href="compare_loaf_pan_clean_10000.html">loaf pan</a> Â· <a href="compare_bowl_gso_clean_10000.html">GSO bowl</a> Â·
<a href="compare_dino_clean_10000.html">dino</a> Â· <a href="noisy.html">noisy meshes</a></p>
</body></html>)rr   ry   Ú	INVENTORYr   Úexistsre   r   ÚtimeÚstrftimerj   ÚCONCLUSIONSr€   )r?   rz   ÚinvÚgalÚobjss   `    r   Úpager°   £   sÇ  ø€ Ý�‰Œ€AØ
�'Š'ð Lð Lõ BKðLñ Lô Lñ Lô L€Cà
�+Š+ð Eð EÝkqð  uDñ  lDð  GSñ  lS÷  k[ò  k[ñ  k]ô  k]ð  	eÐfÐfð  ceÝJPÐS\ÑJ\Ð_kÑJk×IsÒIsÑIuÔIuÐ}ÐEÐEÐ{}ð"ð Eñ Eô Eñ Eô E€Cð �7Š7Ð=Ð=Ð=Ð=µfÐ=Ñ=Ô=Ñ=Ô=€Dð5åð5ð 5õ
 ”Ð.Ñ/Ô/ð5ð 5õ -0°©I¬Ið5ð 5ð .1Ð-C°Oð5ð 5õ ð5ð 5õL ˆQ�„ðM5ð 5ðR ðS5ð 5ð^ LOð_5ð 5ð 5ð 5r   uš  <div class='box'>
<p><b>Findings, from the 1 980 runs below (10 objects Ã— 18 cloud types Ã— 11 configurations) and the gallery.</b></p>
<p><b>The idea that unifies what works: the encoder works at one scale Îµ, the finest detail the input supports</b>, Îµ = max(point
spacing, 4Ïƒ) with the noise Ïƒ given as an encoder parameter (0 for a clean cloud). Surfaces closer than Îµ merge, loops smaller than
ÎµÂ² vanish, and a part is cut only where one smooth height fit fails to explain the points (configuration <b>eps</b>:
<code>eps.py</code>). On a clean cloud Îµ is the spacing and this is the package's slicer with the point test.</p>
<ol>
<li><b>Per-point noise: eps turns the explosion into a description at the noise level.</b> 10k points, all objects, against the
mesh's 139 parts: 0.6 % noise 1 385 â†’ 314 parts, error 0.85Ã— the package's; 1.2 % noise 3 277 â†’ 153 parts, error 0.57Ã—. At 2 048
points and 1.2 %: 742 â†’ 185 parts, error 1.17Ã— (thin limbs are below Îµ there). Measured on the way: the slicer's support, band and
inlier distance must scale with Îµ and the minimum loop with ÎµÂ² (Îµ or a fixed loop leave the specks); the cut margin and the
thin-wall rule must not (scaled by Îµ they delete geometry). C = 4 (<code>report/eps_*.txt</code>).</li>
<li><b>The point test is the cut rule</b> (also inside eps). Everywhere about 10 % fewer parts at the same error at 10k and within
5 % at 2 048; on some organic shapes it keeps pieces the mesh cuts (dress, dino at 10k).</li>
<li><b>Thin walls are an orientation failure.</b> A wall thinner than about a spacing is oriented as one sheet, so the inner face
reads the cavity as inside: the slicer's inside band sits beside the wall and its zero line breaks (<a href="field_loaf_pan_clean_10000.html">field
pages</a>). The thin-wall band (<code>thinwall.py</code>) fixes part of it at 10k (loaf pan 74 â†’ 57 parts, error 16.6 â†’ 9.9; shoe 30 â†’
26) and leaves thick objects unchanged, but it overthickens walls at 2 048 and the wall is not always closed
(<a href="thinwall.html">thinwall.html</a>). The gated hybrid repairs the same rings from neighbouring layers at 5Ã— the cost.</li>
<li><b>Ring refitting (A, the hybrid) gives cleaner rings, not fewer parts,</b> and costs accuracy at 2 048 (8â€“14 %).</li>
<li><b>Variable density: the same idea per point.</b> No global scale fits a cloud whose density varies (a global Îµ from the
90th-percentile spacing roughly halves the parts, <code>report/eps_density.txt</code>). With Îµ measured per point,
Îµ<sub>i</sub> = max(local spacing<sub>i</sub>, 4Ïƒ), setting that point's RIMLS support, band, plane-fit inlier distance and the minimum
loop around it (configuration <b>local</b>, <code>surf_local.py</code>, CPU): gradient density at 10k 927 â†’ 274 parts at 0.53Ã— the
package's error, striped 1 362 â†’ 637 at 0.85Ã—, gradient at 2 048 564 â†’ 264 at 0.88Ã—; per-point noise as global Îµ (0.6 %: 315 parts
at 0.73Ã—; 1.2 %: 168 at 0.67Ã—); clean and mesh-noise clouds about the package's. One measured detail: the flood's balls follow the
local spacing, not Îµ (it seals sampling gaps, and noise opens none; scaling it by 4Ïƒ cost up to 50 % error at 1.2 % noise,
<code>report/local_flood.txt</code>). Weak spot: per-point noise at 2 048 points (0.6 %: 1.13Ã— the package's error).</li>
<li><b>Noise estimation is not solved.</b> A local quadric fit reads thick shapes' noise (horse 0.55 % for 0.6 %) but takes a thin wall's
two faces for noise (clean mug 0.84 %), and at 2 048 everything reads high: Ïƒ is a parameter, not estimated
(<code>report/sigma_estimators.txt</code>).</li>
<li><b>2 048 points is past the sampling limit for this set:</b> about twice the mesh's parts in every configuration, some features gone.</li>
</ol>
<p><b>Recommended, in the paper's words:</b> <i>"Every point carries the resolution the input supports there, Îµ = max(its local
spacing, 4Ïƒ) for a given noise Ïƒ. The slicer resolves nothing finer: its implicit surface is fitted at each point's Îµ, loops smaller
than ÎµÂ² are dropped, and a part is cut only where one smooth fit along the height fails to explain the points."</i> In the package:
a <code>noise=</code> parameter (Ïƒ in world units, default 0), the per-point Îµ in the surf slicer's kernels (CUDA and numba: support,
band, inlier distance, minimum loop; the flood on the local spacing), and the point test as the cut rule for clouds (configuration
<b>local</b>). Later: the thin-wall band with its width from the measured wall, and an estimate of Ïƒ that does not read thin walls as
noise.</p>
<p class="mut">The package is untouched; every prototype is in <code>scripts/</code>. A change to the package is a decision for
<code>api/DECISIONS.md</code>, with these tables.</p>
</div>Ú__main__zsynthesis.htmlzrows ->) Ú__doc__r:   rœ   Úsysrª   Úpathlibr   ÚnumpyrS   ÚpathÚinsertÚstrÚ__file__ÚparentÚparts_reportr   r   r   re   rf   r¨   rA   rr   r€   r™   r°   r¬   Ú__name__r?   Ú
write_textÚprintrj   r   r   r   ú<module>r¿      s¦  ððð ð
 €
€
€
Ø €€€Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ð Ð à Ð Ð Ð à „‡‚��3�3�t�t˜H‘~”~Ô,Ñ-Ô-Ñ .Ô .Ð .Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )ð
Jð 
JÐ+ð 
Jñ 
Jô 
J€ðRð Rð R€ð>ð >ð >€	ðBð ð ðð ð ð,3ð 3ð 3ðOð Oð Oð8=ð =ð =ð@*
€ðZ ˆzÒÐØˆ4‰6Œ6€DØÐÑ×*Ò*¨4¨4°©:¬:Ñ6Ô6Ð6Ø	€Eˆ#ˆ#ˆd‰)Œ)�Y Ð)9Ñ 9Ñ:Ô:Ð:Ð:Ð:ð Ðr   