ST_SNAP behaviour with 3D Geometries

Alexandre Neto <[email protected]> Mon, 13 Apr 2026 18:15:21 +0100
Newsgroups gmane.comp.gis.postgis
Message-ID <CA+H0G_EQ9E08E2fdEX9-dbid0DRxvLtnQNu2gT8uJ3N3YFxVcQ@mail.gmail.com>
--0000000000005e3086064f5aa1e9
Content-Type: text/plain; charset="UTF-8"

Hi all,

I am having trouble understanding the behaviour of St_Snap when used with
3D Geometries.

I was aware that st_snap did not properly support 3D geometries, but I
would not expect that it actually changes the Z coordinates.

I would expect that the Z coordinates would be kept untouched, but that's
not what happens.

WITH input AS (SELECT 'POINT Z (1.001 1.001 50)'::geometry AS geom),

reference AS (SELECT 'POINT Z (1.0 1.0 999)'::geometry AS geom)

SELECT

ST_AsEWKT(ST_Snap(i.geom, r.geom, 0.01)) AS snapped,

ST_Z(ST_Snap(i.geom, r.geom, 0.01)) AS z_after_snap,

ST_Z(i.geom) AS z_original

FROM input i, reference r;




*snapped
|z_after_snap|z_original|--------------+------------+----------+POINT(1 1
999)|       999.0|      50.0|*

In fact, not only the Z coordinate gets changed as it completely ignores
the tolerance.

I then tried to use ST_Force2D around the reference geometry, but the
result is kind of expected, a 2D geometry with no Z coordinate.

I wonder if these are the expected behaviour of ST_snap and there is more a
convenient way to snap 3D geometries in 2D while ignoring the Z component
without needing to recover all vertices Zs from the original geometry.

Thanks,

Alexandre Neto

--0000000000005e3086064f5aa1e9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Hi all,</div><div><br></div><div>I am having trouble =
understanding the behaviour of St_Snap when used with 3D Geometries.</div><=
div><br></div><div>I was aware that st_snap did not properly support 3D geo=
metries, but I would not expect that it actually changes the Z coordinates.=
</div><div><br></div><div>I would expect that the Z coordinates would be ke=
pt untouched, but that&#39;s not what happens.</div><div><br></div><div sty=
le=3D"background-color:rgb(255,255,255);padding:0px 0px 0px 2px"><div style=
=3D"color:rgb(35,38,41);background-color:rgb(255,255,255);font-family:&quot=
;Monospace&quot;;font-size:10pt;white-space:pre"><p style=3D"margin:0px"><s=
pan style=3D"color:rgb(128,0,0);font-weight:bold">WITH</span> <span style=
=3D"color:rgb(142,0,198);font-style:italic">input</span>    <span style=3D"=
color:rgb(128,0,0);font-weight:bold">AS</span> (<span style=3D"color:rgb(12=
8,0,0);font-weight:bold">SELECT</span> <span style=3D"color:rgb(0,128,0)">&=
#39;POINT Z (1.001 1.001 50)&#39;</span>::<span style=3D"color:rgb(0,0,0)">=
geometry</span> <span style=3D"color:rgb(128,0,0);font-weight:bold">AS</spa=
n> <span style=3D"color:rgb(0,100,100);font-style:italic">geom</span>),</p>=
<p style=3D"margin:0px">     <span style=3D"color:rgb(142,0,198);font-style=
:italic">reference</span> <span style=3D"color:rgb(128,0,0);font-weight:bol=
d">AS</span> (<span style=3D"color:rgb(128,0,0);font-weight:bold">SELECT</s=
pan> <span style=3D"color:rgb(0,128,0)">&#39;POINT Z (1.0   1.0   999)&#39;=
</span>::<span style=3D"color:rgb(0,0,0)">geometry</span> <span style=3D"co=
lor:rgb(128,0,0);font-weight:bold">AS</span> <span style=3D"color:rgb(0,100=
,100);font-style:italic">geom</span>)</p><p style=3D"margin:0px"><span styl=
e=3D"color:rgb(128,0,0);font-weight:bold">SELECT</span></p><p style=3D"marg=
in:0px">    <span style=3D"color:rgb(0,0,128);font-weight:bold">ST_AsEWKT</=
span>(<span style=3D"color:rgb(0,0,128);font-weight:bold">ST_Snap</span>(<s=
pan style=3D"color:rgb(142,0,198);font-style:italic">i</span>.<span style=
=3D"color:rgb(0,100,100);font-style:italic">geom</span>, <span style=3D"col=
or:rgb(142,0,198);font-style:italic">r</span>.<span style=3D"color:rgb(0,10=
0,100);font-style:italic">geom</span>, <span style=3D"color:rgb(0,0,255)">0=
.01</span>)) <span style=3D"color:rgb(128,0,0);font-weight:bold">AS</span> =
<span style=3D"color:rgb(0,100,100);font-style:italic">snapped</span>,</p><=
p style=3D"margin:0px">    <span style=3D"color:rgb(0,0,128);font-weight:bo=
ld">ST_Z</span>(<span style=3D"color:rgb(0,0,128);font-weight:bold">ST_Snap=
</span>(<span style=3D"color:rgb(142,0,198);font-style:italic">i</span>.<sp=
an style=3D"color:rgb(0,100,100);font-style:italic">geom</span>, <span styl=
e=3D"color:rgb(142,0,198);font-style:italic">r</span>.<span style=3D"color:=
rgb(0,100,100);font-style:italic">geom</span>, <span style=3D"color:rgb(0,0=
,255)">0.01</span>))      <span style=3D"color:rgb(128,0,0);font-weight:bol=
d">AS</span> <span style=3D"color:rgb(0,100,100);font-style:italic">z_after=
_snap</span>,</p><p style=3D"margin:0px">    <span style=3D"color:rgb(0,0,1=
28);font-weight:bold">ST_Z</span>(<span style=3D"color:rgb(142,0,198);font-=
style:italic">i</span>.<span style=3D"color:rgb(0,100,100);font-style:itali=
c">geom</span>)                              <span style=3D"color:rgb(128,0=
,0);font-weight:bold">AS</span> <span style=3D"color:rgb(0,100,100);font-st=
yle:italic">z_original</span></p><p style=3D"margin:0px"><span style=3D"col=
or:rgb(128,0,0);font-weight:bold">FROM</span> <span style=3D"color:rgb(142,=
0,198);font-style:italic">input</span> <span style=3D"color:rgb(142,0,198);=
font-style:italic">i</span>, <span style=3D"color:rgb(142,0,198);font-style=
:italic">reference</span> <span style=3D"color:rgb(142,0,198);font-style:it=
alic">r</span><span style=3D"color:rgb(255,0,0)">;</span></p></div></div><d=
iv><span style=3D"font-family:monospace"><span><span class=3D"gmail-token g=
mail-token" style=3D"color:rgb(43,48,59)"><br></span></span></span></div><d=
iv><span style=3D"font-family:monospace"><span><span class=3D"gmail-token g=
mail-token" style=3D"color:rgb(43,48,59)"><br></span></span></span></div><d=
iv><span style=3D"font-family:monospace"><b><font size=3D"4">snapped =C2=A0=
 =C2=A0 =C2=A0 |z_after_snap|z_original|<br>--------------+------------+---=
-------+<br>POINT(1 1 999)| =C2=A0 =C2=A0 =C2=A0 999.0| =C2=A0 =C2=A0 =C2=
=A050.0|</font></b></span></div><div><span><span class=3D"gmail-token gmail=
-token" style=3D"color:rgb(43,48,59)"><br></span></span></div><div><span><s=
pan class=3D"gmail-token gmail-token" style=3D"color:rgb(43,48,59)">In fact=
, not only the Z coordinate gets changed as it completely ignores the toler=
ance.</span></span></div><div><span><span class=3D"gmail-token gmail-token"=
 style=3D"color:rgb(43,48,59)"><br></span></span></div><div><span><span cla=
ss=3D"gmail-token gmail-token" style=3D"color:rgb(43,48,59)">I then tried t=
o use ST_Force2D around the reference geometry, but the result is kind of e=
xpected, a 2D geometry with no Z coordinate.<br><br></span></span></div><di=
v><span><span class=3D"gmail-token gmail-token" style=3D"color:rgb(43,48,59=
)">I wonder if these are the expected behaviour of ST_snap and there=C2=A0i=
s more a convenient way to snap 3D geometries in 2D while ignoring=C2=A0the=
=C2=A0Z component without needing to recover all vertices Zs from the origi=
nal geometry.</span></span></div><div><span><span class=3D"gmail-token gmai=
l-token" style=3D"color:rgb(43,48,59)"><br></span></span></div><div><span><=
span class=3D"gmail-token gmail-token" style=3D"color:rgb(43,48,59)">Thanks=
,</span></span></div><div><span><span class=3D"gmail-token gmail-token" sty=
le=3D"color:rgb(43,48,59)"><br></span></span></div><div><span><span class=
=3D"gmail-token gmail-token" style=3D"color:rgb(43,48,59)">Alexandre Neto</=
span></span></div></div>

--0000000000005e3086064f5aa1e9--