# Why does a LINESTRING change in length after union with a shorter but completely-overlapping LINESTRING?

I have two linestrings that I am trying to merge and determine their total length:

This is a contrived example: the green linestring B is fully-contained within the red linestring A (but this will not always be the case), and the length of the merged geometry should be the same as the length of linestring A.

In PostGIS, if I calculate the length of the red linestring A with

select st_length(st_geomfromtext('(A geom)'), false)

I get a result of 0.6102 (arbitrary units).

If I then calculate the length of the union of the red linestring A and green linestring B, via:

select st_length(

st_union(

st_geomfromtext('(A geom)'),

st_geomfromtext('(B geom)')

), false)

I then get a result of 0.6328, even though the green linestring B completely overlaps with the red linestring A.

I've tried many variations of merging these two linestrings involving st_unaryunion, st_linemerge, st_collect, st_dump, st_removerepeatedpoints and no luck.

How can I reconcile this? There are situations where the linestrings to be merged will not overlap 100% and I'll need to measure the length of the total union geometry, but I have trouble trusting that number when it seems to fail in this scenario.

For what it's worth, linestring A is:

MULTILINESTRING((-84.3381536299124 33.7648637741265,-84.337082 33.76486,-84.3370269 33.7648551,-84.3367653 33.7648604,-84.336237 33.764861,-84.3358725 33.7648538,-84.335818 33.764857,-84.335192 33.764848,-84.3350945 33.7648474,-84.335009 33.764844,-84.334164 33.764846,-84.333928 33.764846,-84.3337994 33.7648477,-84.332997 33.764858,-84.332176 33.76486,-84.331834 33.764852,-84.330605 33.764845,-84.330119 33.764848,-84.329495 33.76486,-84.328663 33.764858,-84.327896 33.764867,-84.3275311259472 33.764859190368))

linestring B is:

MULTILINESTRING((-84.3372103956974 33.7648604521912,-84.337082 33.76486,-84.3370269 33.7648551,-84.3367653 33.7648604,-84.3365005784092 33.7648607006492))

EDIT: an added wrinkle: The length of linestring B is 0.04079. If I measure the intersection between both linestrings:

select st_length(st_intersection(st_geomfromtext('(geom A')),st_geomfromtext('(geom B)'), false)

I get a result of 0.01821, which implies that there is (0.04079 - 0.01821) = 0.02258 of its length that doesn't overlap, which is the difference measured between st_length(A) and st_length(union(A,B)).

EDIT 2: this is getting weirder! I ran ST_SymDifference to find the area where these lines didn't intersect/overlap. It looks like this:

So the point where the line doesn't cross the green dots is where both linestrings overlap, and that coincides to all of the points in linestring B that have identical matches in linestring A, which is every point except the first and last points of B.

So if I take the first point of linestring B (we'll call it P): POINT(-84.3372103956974 33.7648604521912) and see if it intersects with linestring A:

select st_intersection(st_geomfromtext('(geom A)'), st_geomfromtext('POINT(-84.3372103956974 33.7648604521912)'))

I get "GEOMETRYCOLLECTION EMPTY" as a result.

If I then try to find the point on A that is closest to P, it is identical to P:

select st_astext(st_closestpoint(st_geomfromtext('(geom A)'), st_geomfromtext('POINT(-84.3372103956974 33.7648604521912)')))

The result is "POINT(-84.3372103956974 33.7648604521912)"!

On top of that, this also fails:

select st_intersection(st_geomfromtext('(geom A)'), st_closestpoint(st_geomfromtext('(geom A)'), st_geomfromtext('POINT(-84.3372103956974 33.7648604521912)')))

The result is "GEOMETRYCOLLECTION EMPTY", which seems quite broken since I'm requesting the intersection of a linestring with a point explicitly generated as being on that linestring. This query fails with the last point of B as well, but works with points 2, 3, and 4. The order of arguments (geom first, point second or vice versa) does not affect anything.

``````MULTILINESTRING (( -84.3381536299124 33.7648637741265, -84.337082 33.76486 ), ( -84.337082 33.76486, -84.3370269 33.7648551 ), ( -84.3370269 33.7648551, -84.3367653 33.7648604 ), ( -84.3367653 33.7648604, -84.336237 33.764861, -84.3358725 33.7648538, -84.335818 33.764857, -84.335192 33.764848, -84.3350945 33.7648474, -84.335009 33.764844, -84.334164 33.764846, -84.333928 33.764846, -84.3337994 33.7648477, -84.332997 33.764858, -84.332176 33.76486, -84.331834 33.764852, -84.330605 33.764845, -84.330119 33.764848, -84.329495 33.76486, -84.328663 33.764858, -84.327896 33.764867, -84.3275311259472 33.764859190368 ), ( -84.3372103956974 33.7648604521912, -84.337082 33.76486 ), ( -84.3367653 33.7648604, -84.3365005784092 33.7648607006492 ))