1 Reply Latest reply on Oct 2, 2012 1:50 PM by matt schell

    SDO_LRS.LRS_INTERSECTION and tolerance

    Paul Dziemiela
      Hi folks,

      Not sure if this a bug or an enhancement request or confusion on my part. I've never been a great fan of LRS_INTERSECTION and how it coughs out ORA-13331 in such an unfriendly manner but it is what it is and I try to use it. As a function it does an intersection upon two geometries and then applies the proper set of measures to the output. So we have two sets of calculations going on against two separate sets of dimensions, one against X and Y in one set of units and one against M in another set of units. But just one tolerance input parameter.

      So when we give a tolerance to this function, what exactly are we giving?


      Many LRS functions require that you specify a tolerance value or one or more dimensional arrays. Thus, you can control whether to specify a single tolerance value for all non-measure dimensions or to use the tolerance associated with each non-measure dimension in the dimensional array or arrays. The tolerance is applied only to the geometry portion of the data, not to the measure dimension. The tolerance value for geodetic data is in meters, and for non-geodetic data it is in the unit of measurement associated with the data.

      So my reading of that would say that the tolerance value should be applied to the XY intersection of the two input geometries and the LRS tolerance is just unstated, probably using the default of 0.00000001. However, today I was noticing some odd results from the function when the intersection is very small. I have a polygon and an LRS line which definitely overlap at 0.05 meter tolerance but just barely with a result only 0.062 meters long! Yes, that is cutting it close.

      Anyhow I cling to the 0.05 meter tolerance for geodetic data like all the rest of you and am happy with my intersection functioning at that tolerance. If the overlap was 0.04 meters long I would be fine and dandy with getting back nothing. But its not. So I provide LRS_INTERSECTION with a tolerance of 0.05 meters expecting to get back something.

      I get back nothing.

      As I mentioned if I use SDO_INTERSECTION I get back my 0.062 meters of overlap (with hosed measures of course). But LRS_INTERSECTION returns NULL. So after mulling this a bit I changed the tolerance input to 0.00001 and voila - there are my results! I feel pretty sure that the one function input tolerance is being used for both the XY intersection and the M measure evaluation. This does not seem like a good thing at all. Screwing about with 0.075 tolerance returns the dreaded LRS point because at that tolerance the two geometries are just touching. Try running my code block below with 0.05, 0.075 and 0.00001 and note this confusing results.

      So one solution would be to do what the documentation says:
      Be sure that the tolerance value used is appropriate to the data and your purpose. If the results of LRS functions seem imprecise or incorrect, you may need to specify a smaller tolerance value.

      But my geometries may not be valid at 0.00001 meters of tolerance. What happens to the intersection step with invalid geometries? Also, if they don't intersect at 0.05 meters, I don't want any results. Can anyone shed some light on the matter?

          sdo_polygon SDO_GEOMETRY := SDO_GEOMETRY(
          sdo_lrs_line SDO_GEOMETRY := SDO_GEOMETRY(
         sdo_temp SDO_GEOMETRY;
         num_tolerance NUMBER := 0.05;
         --num_tolerance NUMBER := 0.075;
         --num_tolerance NUMBER := 0.00001;
         dbms_output.put_line(' ');
         dbms_output.put_line('Using tolerance ' || num_tolerance);
         -- Check Polygon and LRS line are valid 
         dbms_output.put_line('Validate polygon: ' || SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(sdo_polygon,num_tolerance));
         dbms_output.put_line('Validate LRS line: ' || SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(sdo_lrs_line,num_tolerance));
         -- Polygon and LRS line are OVERLAPBYDISJOINT at 0.05 meters, there is overlap you can see in mapviewer
         dbms_output.put_line('SDO_GEOM.RELATE: ' || SDO_GEOM.RELATE(sdo_polygon,'DETERMINE',sdo_lrs_line,num_tolerance));
         -- Running generic SDO_INTERSECTION returns a valid linestring but of course hoses the LRS values
         -- No points or whacky collections or anything iffy or squirrelly, but very small
         sdo_temp := SDO_GEOM.SDO_INTERSECTION(sdo_polygon,sdo_lrs_line,num_tolerance);
         dbms_output.put_line('SDO_GEOM.SDO_INTERSECTION: ' || sdo_util.to_clob(sdo_temp));
         dbms_output.put_line('SDO_GEOM.SDO_INTERSECTION length: ' || sdo_geom.sdo_length(sdo_temp,num_tolerance,'UNIT=M'));
         -- Running LRS_INTERSECTION at 0.05 tolerance returns NULL, not ORA-13331 or anything, just NULL
         sdo_temp := SDO_LRS.LRS_INTERSECTION(sdo_polygon,sdo_lrs_line,num_tolerance);
         dbms_output.put_line('SDO_LRS.LRS_INTERSECTION: ' || sdo_util.to_clob(sdo_temp));
         dbms_output.put_line('SDO_LRS.LRS_INTERSECTION length: ' || sdo_geom.sdo_length(sdo_temp,num_tolerance,'UNIT=M'));
         -- but what is tolerance being applied to?  To the 2D geometry intersection or the measure calc?
         -- it looks to be both!
        • 1. Re: SDO_LRS.LRS_INTERSECTION and tolerance
          matt schell
          Hi Paul,

          I follow what you've laid out and agree - this is either a bug or unclear documentation. I recreated your results on here.

          Most of my experience using sdo_intersection (no experience with lrs_intersection) is in cartesian, FWIW. But I've never seen sdo_intersection throw any errors or produce unexpected results intersecting at .000--veins-of-a-butterflys-wings-0001 tolerance when the input geometries aren't actually valid at that tolerance. You could even temporarily NULL out your geodetic sdo_srid for the two inputs before sending them to sdo_intersection. Cleaning the output of unintended and invalid at .05 results however, ... good luck with that.