10

I have geometry records of type MultiLineStringZM and I am trying to INSERT new records that overlap some of the records currently in the table. If they were type MultiPolygon I could use ST_Area() as in the following

SELECT
    a.id
FROM
    a, b
WHERE
    ST_Area(ST_Intersection(a.geom, b.geom)) > 0.5 * ST_Area(a.geom);

to identify the polygons that overlap by a majority. However ST_Area() is not a compatible function for MultiLineStringZM, and the above query does not return any results.

ST_Covers(), ST_Within() & ST_Intersects() will either not return any results or return too many depending.

How can I identify & delete all records overlapped by a 'majority' or some specified fraction for this geometry type?

10
  • Are the lines perfectly covering each others (where they overlap), or is there a tolerance to consider?
    – JGH
    Commented May 31, 2017 at 2:14
  • 1
    if like you said st_area is not compatible with MultiLineStringZM then try using the ST_Force_2D to convert the geometries to 2D
    – ziggy
    Commented May 31, 2017 at 3:28
  • and then convert to 4D? St_Area(ST_Force2D(geom))? Is any information lost by doing so?
    – Don
    Commented May 31, 2017 at 6:57
  • @JGH they do not most of the time, but do directly overlap the lines > 40-50%
    – Don
    Commented May 31, 2017 at 7:01
  • 2
    Did you try ST_Length? Only works when the coordinates of the lines are perfectly aligned, as @JGH mentioned.
    – tilt
    Commented May 31, 2017 at 9:19

1 Answer 1

1

You could try this, which finds the intersection and calculates the total length of the intersection, then compares that to the line length. Change the tolerance as needed (I'm assuming you want less than 50% overlap):

select id from 
  (select 
    a.id,
    st_length(st_union(st_intersection(a.geom,b.geom))) ilen,
    st_length(geom) len
  from
    a,
    (select st_union(geom) geom from b) b
    group by a.id
  ) foo 
where ilen/len < 0.5;

If you also need to account for an intersection tolerance (if lines are less than 1 m apart, is that still an intersection?), you can use buffers and st_area to determine overlap %. I'm assuming your srid is lat/lon. If it's projected, you don't need the geography casting.

select id from 
  (select 
    a.id, 
    st_area(st_union(st_intersection(a.geom,b.geom))) iarea,
    st_area(geom) area
  from 
    (select id, st_buffer(geom::geography,1)::geometry geom from a) a,
    (select st_union(st_buffer(geom::geography,1)::geometry) geom from b) b
    group by a.id
  ) foo 
where iarea/area < 0.5;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.