From 9b9adabecadbc80137225152985aa751ce629c3a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 22 Jun 2024 23:07:06 -0400 Subject: [PATCH] Attempt a simple rebuild of PolySet on Manifold error (#5183) --- src/geometry/manifold/manifoldutils.cc | 19 ++++++++++++++++- .../scad/3D/features/polyhedron-soup.scad | 20 ++++++++++++++++++ .../cgalpngtest/polyhedron-soup-expected.png | Bin 0 -> 7909 bytes .../dumptest/polyhedron-soup-expected.csg | 2 ++ .../opencsgtest/polyhedron-soup-expected.png | Bin 0 -> 7909 bytes .../polyhedron-soup-expected.png | Bin 0 -> 7909 bytes 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/data/scad/3D/features/polyhedron-soup.scad create mode 100644 tests/regression/cgalpngtest/polyhedron-soup-expected.png create mode 100644 tests/regression/dumptest/polyhedron-soup-expected.csg create mode 100644 tests/regression/opencsgtest/polyhedron-soup-expected.png create mode 100644 tests/regression/throwntogethertest/polyhedron-soup-expected.png diff --git a/src/geometry/manifold/manifoldutils.cc b/src/geometry/manifold/manifoldutils.cc index 6c887252424..716742a095c 100644 --- a/src/geometry/manifold/manifoldutils.cc +++ b/src/geometry/manifold/manifoldutils.cc @@ -1,6 +1,7 @@ // Portions of this file are Copyright 2023 Google LLC, and licensed under GPL2+. See COPYING. #include "manifoldutils.h" #include "ManifoldGeometry.h" +#include "PolySetBuilder.h" #include "manifold.h" #include "printutils.h" #ifdef ENABLE_CGAL @@ -113,7 +114,23 @@ std::shared_ptr createManifoldFromPolySet(const PolySet& ps) return mani; } - // FIXME: Should we suppress this warning, as it may not be very actionable? + // Before announcing that the conversion failed, let's try to fix the most common + // causes of a non-manifold topology: + // Polygon soup of manifold topology with co-incident vertices having identical vertex positions + // + // Note: This causes us to lose the ability to represent manifold topologies with duplicate + // vertex positions (touching cubes, donut with vertex in the center etc.) + PolySetBuilder builder(ps.vertices.size(), ps.indices.size(), + ps.getDimension(), ps.convexValue()); + builder.appendPolySet(ps); + std::unique_ptr rebuilt_ps = builder.build(); + rebuilt_ps->setTriangular(ps.isTriangular()); + mani = createManifoldFromTriangularPolySet(*rebuilt_ps); + if (mani->getManifold().Status() == Error::NoError) { + return mani; + } + + // FIXME: Should we attempt merging vertices within epsilon distance before issuing this warning? LOG(message_group::Warning,"PolySet -> Manifold conversion failed: %1$s\n" "Trying to repair and reconstruct mesh..", ManifoldUtils::statusToString(mani->getManifold().Status())); diff --git a/tests/data/scad/3D/features/polyhedron-soup.scad b/tests/data/scad/3D/features/polyhedron-soup.scad new file mode 100644 index 00000000000..b70203cc6e8 --- /dev/null +++ b/tests/data/scad/3D/features/polyhedron-soup.scad @@ -0,0 +1,20 @@ +polyhedron(points = [ + [1,0,0], [0,0,1], [0,1,0], + [1,0,0], [0,1,0], [0,0,-1], + [1,0,0], [0,-1,0], [0,0,1], + [1,0,0], [0,0,-1], [0,-1,0], + [-1,0,0], [0,1,0], [0,0,1], + [-1,0,0], [0,0,-1], [0,1,0], + [-1,0,0], [0,0,1], [0,-1,0], + [-1,0,0], [0,-1,0], [0,0,-1], +], +faces = [ + [0,1,2], + [3,4,5], + [6,7,8], + [9,10,11], + [12,13,14], + [15,16,17], + [18,19,20], + [21,22,23] +]); diff --git a/tests/regression/cgalpngtest/polyhedron-soup-expected.png b/tests/regression/cgalpngtest/polyhedron-soup-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0275282621e88d939794156e0f761adf88de7e GIT binary patch literal 7909 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 literal 0 HcmV?d00001 diff --git a/tests/regression/dumptest/polyhedron-soup-expected.csg b/tests/regression/dumptest/polyhedron-soup-expected.csg new file mode 100644 index 00000000000..8898f2eff3e --- /dev/null +++ b/tests/regression/dumptest/polyhedron-soup-expected.csg @@ -0,0 +1,2 @@ +polyhedron(points = [[1, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 0, -1], [1, 0, 0], [0, -1, 0], [0, 0, 1], [1, 0, 0], [0, 0, -1], [0, -1, 0], [-1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, 0, 0], [0, 0, -1], [0, 1, 0], [-1, 0, 0], [0, 0, 1], [0, -1, 0], [-1, 0, 0], [0, -1, 0], [0, 0, -1]], faces = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19, 20], [21, 22, 23]], convexity = 1); + diff --git a/tests/regression/opencsgtest/polyhedron-soup-expected.png b/tests/regression/opencsgtest/polyhedron-soup-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0275282621e88d939794156e0f761adf88de7e GIT binary patch literal 7909 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 literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/polyhedron-soup-expected.png b/tests/regression/throwntogethertest/polyhedron-soup-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0275282621e88d939794156e0f761adf88de7e GIT binary patch literal 7909 zcmeHM`9GB1`#<*>%xKDJNS2tEXDEe)Nns`mErZZHX*@*|BFd69xAsU{NS2VNcs$us zS+dM1LdvLwWSJKGnsqEQ_xE@{-|y@D4}5?6zWQNa_ciCf?(3ZEea^YA_jS&7dt2*; za;kCwfQ8#_wmJZSgCY(P<{u%dmRazD_&Zozfb2T;UifFD+y3pxSS+vx$^?L1^#J&J z75GzyKlo`1?tfZvAVunb<@uM|`msC!G}zm>ZgC1i2HVW?2C7fV)YD0;Ewa^BMmuX$ zNm*fO#wmn#m(!N$KO~$)X-(9N8lf#mt5bIlXJ{r!eV@=nv$wkK(b!Zm7@_O>ATuK; ztnBC9$V9&#XYMLMaQHsrTxxst`}^~98Ib_`Q7CPb#xp;>Nic?Oc+`lAg0NH^F6HR-a%Bi)s=X5vD0-K8P^e5M z*e``AkhRxPLAY`Ib0V2a1)0!1K~aeewyF8Fz?WpuI6sPTIRcs*N%w{?3BdFBaDJon zd+q#x-dTe_IIcuV78e79PUlcl(kv$c)8vY4TjY*$4l+UXNp4#WClJFVya<%^cQNU$ z;1G!B;64LgHr94mQ^np}>HhE@7+{Do_@R7>+o*xdLtlGqCTQqAGaYxHH;aj4yBVH} zD!Glmhqf?*Q;*-YiTT-qF>+^zWP+nnHna`r2xHFbuO}RI!iE{5ob$hgBMj_^rW;>M zS&s!n7R@`;!&y3MKr$uZF40%XwcmLEFca+R`2G*2b*{Nv!$zhxA;@h9g6O-kYwh}K zWU)bA1DE2M4OL2_Z~aZlZ?X<|;!jE&dx`auu+|%s2_2H&DX!?p`-t^D;_)E^P@JQ0N8C4aVmtJ9PYl$)|%ONX`9SbGz}TIMv6Fedly@-TONvbM8g$ zom=WVo1djfSCkv#hCrH!+vn>8U&K)=Me-ZFx}2vWq7sdaks{{Y5Vtg+6x1%oQ`yg7 znG%+;@8!598w-QDxC$;bs@~Kh`^xHXq4cx9)em)q*95-GS{3=pnF&t&gy90@#=nYl z0WRtMzq=3i$R=OoV>{6op7r$2N^ucIxJQG$k!|LBVme;Mki zuMK5d?y{VKF+No69Gbw4Z^I5|lbRci-QASQ;LB#G(z4pdWUnb+z*ZS2PMqUA4%qeK z%>k_sC;NRSr1_Q}9YlufuOsIXfnJDI07h|f;}ffO6_!)M z3a7{-j?23&Zd^KPzqUGQ6&1*wXe@bbH6(c`;3mDO2z(`QElJwJ1dmQwmmawiI^f^& z&jgF#SzsVcs@C~}$20S9I{l+HdXcMatx|uvZJYc80{Z%NyC{yox)_@la9#QCwXcfp zAOPup#m)4v>l(ABUVoEeQFCK$h?7tr=abGEf$tcxb}yFe=3H@bs^AoWeWH=hM!VRDs|%+KD- zJ2d1(`z*{MXe-0cv$;v#j9Q+B-};H+JBPH@$KmAEH*x!(OnntQK7A=~^LbHarZk>^ z@b#(9NHO--K_*jQowk?^uE($6zB)FGH#L;pJuQexnz0p0-{d@4Nd`4(>Am>NZ{EI~(86%SLAhUnTYRo3*4s0IVa3`FPK|BcOc~P>V&SeW zGB-X~J$#}BEDMImzne{Z?9i2p_fz#MfB>`hPA%+Zh@wPu)-nxZ*)`?wq?s3JKlRFG zv1*MP)W-QJ4?>W0dTuCzIU_HjJl`&}tG+@ZoeHc5TCN*KJ)4D}y6;>Ws#UVB#-s|5 z=dUlo4UaZ=x6&BJ#6qX#Qgz#3*TSw1 z!Xd`{v1DbH`jlr^s3WB)5Vij$veTGdwI2u!_!m>~@8h!Yh(6moO5o0ymsDvb%sw!n z26DSHY{9!vwNb|mM*p?2ZrN$gTsR6fIEz+)2iuJ`Yq|L(x8WbH-MjlQh}Q1SO=&~7 z8KMFO8`HPXNWPR?g&r4Ux;R9W{jcL=HrF;X#AC@zLlgv68&pOFV5?h# z7(^9cpYJh8aX8_9_E6ya*=DVRknX-#+0!TaXsj}jG9ElrV`MH;p2NAcO;WE(f}Jbv$tzEmq7A1>JV9Nd5WL}T{d$C|;hTgca}#A&#uOkGt5E01W- zMKG`fIkxlpqhucw3@GgkD3h1esQR5Zk>4PkGdOf=D~$X{n$BkzHOpej>4UtE1tJ4s z>Fo_==M=!}>{Ab0ZGtl6cs8%{ty}h-B<+X}dcryCtVG9NP;>dBAj1<usSU9q7+!Wt@Q!Zh2>@`8LL7isu>8%?MmI%(;aO zN1jMt4(?2J98Gpzs8Xt~qJLJ_vR@fIEZHnORnFDA|A|NzZ53Y4;c#buirc?h@f)#^ zAI6enO^3PD^O>*fQ3v)dik>5SngUbb1s1*252t~T@tn>lEsII&qNJrIVaq!g zpybB3i;~yF0ldfW)J!pt&waC`<3@R>WMDwOXl(lhf0NMaiehJ)6)LW`uLK_rKe3qc zd!yHEm5Dwv_1;yQzwnwSahI;IKgBmLi*&!FQ;@C&lD;NlYIG#9s|*yb^cZ;+Dr2~` zfh+}g3zCrLiql*GO(vjG+pelJ!79&$1k`n5Tp@Jxlt0~;1-vf#9h5}`+|&!bK#U*B#nTb_10_pozITy7o7VfTfC=w!l^qB0rq}`PI@A5`DCWkG z8!gTL1Dvh#Da=kl7uwi*=uo9v&eAklV3p6UQNp;QuV%d?L(+nywu|oSM3)dp=DP3x zF*Y62L`RaNj$L{O6OMmigH=ite-m8xmQegY0OeQV$_CLPaAs^C4G-HLhU(PyH@JoynR&ixUTE)Gd@~ zUj<)H{c;1ymJB~A5)!p?Tk(m3+xN*)$l%ZCr=$cy6yda8>sb%;(L2aVT>RH0(-g2# zrL~jrj!Km}*7H4959jjEye^2Me@v@y?>Z@3Pbs*ca{aYk`B?H6cA+ajWkQDyNX0U( zc+%IG({fX8{1h{#|ExO)!dg0FK;6a&Sh5@hTzI@GG&}(axDHtvQkB)H)bZ`@E5IE? z3l+S~lKloQLX+sV&VbZDx%wndW;kq=M?ACv2KlFZFM_2{IM4R?>Yo(rq+1Vi$O8&j&n@e1S}`pLexp`tB%>bfq@AZ5X9dxRWXdZf;0C4@(< zs^YI|wBr4=rw5M8jWXWXLvz^>Lm`q2VewrH3x92dj_l5he4_*+sdq^ms#$0^V|!yQ z(XAS#+>+;5061e-IJ_~j8fEP=vt10#8Z2{6s#(mx!^)pQH>vDBeG2~;_U?p327Js^ zMCvhXB7>0URwnc*7ODrV4p=Lkd5aQ0zdkBA&z)>gzB$5?85j#^ut9}dV3Ea80;;=8 zH+~C07EyVb+W-@foUA(`NaBCRZ^%<*K(*uInMsGAXIHS8p1Xg%SbPh~TE$Se2ImMp zgLs0v!Y#zQ;ULc%JYT{xI-K{Pd0JEn&l{fQgt@BdZ!VY~B>PfwrF6QS5b}=`PS71f zHQZrg=>(M7y4JG05N;){+Osx$uabJ2$w<9I$72}dXudUo>CG{9BDZHC;J>l+SLyW$qJJ13o`n30kpTun{FCMUhUV2?R5fl%O zU-Qt$;msG1xbdye&33E>lL?WtH*M)i5_Y55wJxVM7IBYXfNpr<909_nU}P@c{nrLO zb7l4JE4`;F`f^d5?!p24tNse?KJ;eKTe%>KWB!CJO(MX?r(y%eeLTq&Kcuu1p37`R zjYVu-I>MEF7W&&uR^ghKapP`eaUX8%W`e{Y18eYvxjn*TpLk^_`iJw(&x>Xz(sh*s zKGfmTTk%1XPervRx|nYjC-&GB$1^c_V3BZ_chd^{ZNkAc?&aKxDQ7Y+C5Ov&N?lgo?iuLPa96gR|U*H zrm-=L+duisn0KtSFESm%idI^C&xTo7i8nLKt+(DkcJD?{zX@{yi`@9LmV^R#C_9~js`cnm5 zb1$nph}UX1cJ)0=6c7lA38{}PaB+ciXVeBHo{=6mrTK$Y{ zl(W>u`*1Gfi)jCJj3v9jU+P)KIrb;Cf6NT7`hdxc!9_$7@CoiuNszoa&&EDh70KiI ztzx5MN9il=<2erb632bJh9jnRQref}v|kWaj9z{Zle zi@Qvlmhlrqjh>X^lmg}|D;jzBiVQNSROT1=+KE}r3>Mbn!N!V}IQ>(&l)bzNLB8-N z?{q8F+qfTpP8Js7LAoQO3FuD_aB3fqz1bpGmXq~F0_P*(214_%CgJQJhGp)_m$(}o<|&W?oqGPy!_41Sqf-*K z$Xl%WD|ieRoUjl(snC3m;!@S|s;FO`jp^!Y@gVDgIrku zb~Te9hlN!fY;-1d8K#jwt&=b5dL&aKM*uqCQuxD??hg5~PhX7}G|$i-O@3X2fgrWZ zECOA+U%N%4dFJa`)xm$s_4mq9+!2@LrrKxTV!hzGyvHawp5d`}`$&yy?gTfryHpke zff)J(ucXSf1GAYIZP@MbrX!FfX8Lq~sN}yH`Z`0mFv%){-`Sqv592HNf$ANYOF!2B z+Rh!;#?LBi58ExyWc&1UJU0&gL4|Zixioue?u4@Q%r#U>w1@d&5$#;&M;%YEVX2vEQ2QGUjUsYI$%wJ z*;r!tHH6LWGD^#bM+9pX7x@uM@%Vhnp;{XwJyLso=3 z`Q8Qx7elW1Na5}A)%E%^UgC9XM>Aa^Q9EE6{mDsqcUA5L-TQL60VJn4oOe62!%Cs& zKK(w=pFB&rPQ`EIB)W-MoF9?bd7ymka*|SYu3g literal 0 HcmV?d00001