Vs MDSYS Haversine formula. SDO_GEOM. SDO_DISTANCE

We need calculate the distance between 2 lat/long (from the GPS unit).

What is more precise, the use of MDSYS. SDO_GEOM. SDO_DISTANCE or a hand coded formula Haversine?

Thank you
JB

Well, the best thing to do is to perform a test.

I looked at this website: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

The answer to the default functional demo is 969954.114 meters.

Test with SDO_DISTANCE, we get (I converted values DMS to DD):

select sdo_geom.sdo_distance(
          sdo_geometry(2001,8307,sdo_point_type(-5.71475,      50.0663222222,null),null,null),
          sdo_geometry(2001,8307,sdo_point_type(-3.07009444444,58.6440222222,null),null,null),
          0.05) as dist
  from dual;
-- Result
--
969954.113110585

Which is pretty similar!

So, don't bother coding your own Haversine (you need to add additional parameters to pass in parameters to ellisodal for non - WGS84 SRID...), use what comes out of the box.

That answer your question? If so, please give points.

concerning
Simon

Tags: Database

Similar Questions

  • Performance SDO_DISTANCE

    Table A_SPATIAL has 15 million records with different values of longitude and latitude. I also have the SDO_GEOMETRY shape, which stores the column SDO_GEOMETRY (2001, 8307, MDSYS.) SDO_POINT_TYPE (LONGITUDE, LATITUDE, NULL), NULL, NULL).

    I created the function and the index below:

    create or replace function get_long_lat_pt(longitude in number,  
                                             latitude in number)  
    return SDO_GEOMETRY deterministic is  
    begin  
    return sdo_geometry(2001, 8307,  
                    sdo_point_type(longitude, latitude, NULL),NULL, NULL);  
    end;  
    / 
    INSERT INTO user_sdo_geom_metadata VALUES(  
    'A_SPATIAL', -- table  
    'SHAPE', -- function  
       mdsys.sdo_dim_array( 
          mdsys.sdo_dim_element('LONGITUDE', -180, 180, 0.005),  
          mdsys.sdo_dim_element('LATITUDE', -90, 90, 0.005)  
       ), 
       8307  -- SRID  
        ); 
    commit;  
    CREATE INDEX A_SPATIAL_SHAPE_IDX  
    ON A_SPATIAL(Shape)  
    INDEXTYPE IS MDSYS.SPATIAL_INDEX;  
    
    

    Then when I run the query below, it performs a full table scan. Even though I have the index above, the index get used because I use SDO_DISTANCE to wrap around her, I guess. The longitude and latitude provided to the get_long_lat_pt function below are some user input, and they all vary.

    select * from A_SPATIAL where  
    SDO_GEOM.SDO_DISTANCE(SHAPE, get_long_lat_pt(95.224, 31.601), 1, 'unit=MILE') < 20;  
    
    

    Issues related to the:

    1. What is the optimal way of running this query to perform the best? I guess the full table scan is obvious as I need to calculate the distance, but is there a way to improve the performance?

    2 is the index above or even useful at all?

    3. I use SDO_WITHIN_DISTANCE in my case, but it would run a full table in any case scan because I still need to calculate the distance. He would perform better than the example above?

    Thank you.

    The only difference in your queries (Simplified) is the max_resolution of the additional parameter, it is only applied in the other, but max_resolution = 400 is big enough?

    Don't know if it makes a difference separating the parameters with ',' I got the same result.

    'distance=400, max_resolution=400 , unit=mile') = 'TRUE';
    
    'distance=400 max_resolution=400, unit=mile') = 'TRUE';
    

    You can try to force ORACLE to use the INDEX and the execution of test plan:

    SELECT /*+ INDEX (g a_spatial_shape_idx) */
           SDO_GEOM.SDO_DISTANCE(shape, get_long_lat_pt(95.224, 31.601),0.001,'unit=mile') dist
      FROM a_spatial g
     WHERE SDO_WITHIN_DISTANCE(shape, get_long_lat_pt(95.224, 31.601),'distance=400 unit=mile') = 'TRUE'
     ORDER BY dist;
    

    If you can use the postal code instead of lat/lon for the query results, of course, create an index on the zip code, use it in the WHERE clause and test execution plan.

  • issue of sdo_geom.sdo_intersection

    Hello
    I am new to oracle spatial, and I'll try to find the point on a line which is closest to another topic.

    to do this, I use the SDO_NN_distance to find the distance of my object point to the line closest to you.
    I then use this distance as being the distance of entry to create a buffer around mysubject point.
    I then use the SDO_geom. SDO_intersection to find the intersection of my stamp and my line. This intersection is expected to be the closest point on my line to the point of topic.

    However this does not always work. Here's what I find so far and for which I can't find an explanation.

    1. when creating the buffer, I need to set a very low tolerance so that the buffer to be round. Is there another way to do it.
    2. Despite everything when I look at my pad and my line, I see that the buffer does not touch the line my buffer distance is a bit too small why?
    3 - when I try to get the intersection using sdo_geom.sdo_intersection and don't receive no value. I guess it's because my tolerance of buffer is so small that it cannot extend far enough to touch the line?


    That's what I'm developing as the solution so that the bearing from one point to the nearest point of the nearest line. but for this I need to get X and Y on the point on the line in order to calculate the azimuth beetwen my topic as well as on the line.

    Any help is appreciated.


    Thank you

    Thierry

    Hello
    You can try the function below - note that the distances are arbitrary. You can experiment with different values. The function is not robust, for a production system, check the geometry types are passed into the function.

    Select near_point (sdo_geometry (2001, null, sdo_point_type (3,1,null), null, null),)
    sdo_geometry (2002, null, null, sdo_elem_info_array (1,2,1), sdo_ordinate_array (0,0,1,2, 10.5)))
    Double;

    Kind regards
    Pieter

    FUNCTION to CREATE or REPLACE near_point SDO_GEOMETRY RETURN (point SDO_GEOMETRY, line SDO_GEOMETRY) IS
    Dist NUMBER;
    x NUMBER;
    y NUMBER;
    SDO_GEOMETRY arcs;
    MDSYS inter1. VERTEX_SET_TYPE;
    intersect_line SDO_GEOMETRY;
    MDSYS INTER2. VERTEX_SET_TYPE;
    dir NUMBER.
    avgx NUMBER;
    avgy NUMBER;
    BEGIN
    Dist: = sdo_geom.sdo_distance (point, line, 0.0010) + 0.10;
    x: = point.sdo_point.x;
    y: = point.sdo_point.y;
    -create arcs around the point
    arcs: = sdo_geometry (2002, point.sdo_srid, null, sdo_elem_info_array (1,4,2,1,2,2,5,2,2),)
    sdo_ordinate_array (x, y + dist,)
    x + dist
    x, y - Dist.,
    x Dist
    x, y + dist));
    -intersect with the line bows
    inter1: = sdo_util.getvertices (sdo_geom.sdo_intersection (arcs, line, 0.001));
    -get the average between the first and last point of intersection
    avgx: = (inter1 (1) .x + inter1 (inter1.count) .x) / 2;
    avgy: = (inter1 (1) there + inter1 (inter1.count) there) / 2;
    -take in the direction of the point to the average of the coordinates
    dir: = atan2 (avgx - x, avgy - y);
    -create a point in the direction of the average line, increase the distance allowing the bows online
    intersect_line: = sdo_geometry (2002, point.sdo_srid, null, sdo_elem_info_array (1,2,1),)
    sdo_ordinate_array (x, y, x + sin (dir) * (dist + 10), y + cos (dir) * (dist + 10)));
    -get intersections
    INTER2: = sdo_util.getvertices (sdo_geom.sdo_intersection (intersect_line, line, 0.001));
    RETURN sdo_geometry (2001, point.sdo_srid, SDO_POINT (inter2 (1) .x, inter2 there (1), null), null, null);
    END;
    /

  • sdo_distance

    Hi, I took the following limits for 32616 EPSG SRID and trying to calculate the distance.

    Proposed limits:
    166021,44 0.00
    534994.66 9329005.18

    SELECT sdo_geom.sdo_distance (sdo_geom.sdo_geometry (2001, 32616, sdo_geom.sdo_point_type (166021.44, 0, NULL), NULL, NULL))

    sdo_geom.sdo_geometry (2001, 32616, SDO_POINT (534994.66, 0, NULL), NULL, NULL), 0.0001, 'unit = COUNTER') distance_in_m

    from DUAL;

    I get the result 368973,22 m (368 km), I think that the distance should be approximately 600 km.

    Please help me if I'm wrong.

    Thank you

    The spherical difference should be smaller, your second point seems not wrong, here you can compare:

    SELECT sdo_cs.transform(sdo_geometry(2001 ,4326 ,sdo_geom.sdo_point_type(-90, 0, NULL), NULL ,NULL),32616) FROM dual
    --------------
    (2001; 32616; (166021.443179323; 0; ); ; )
    
    SELECT sdo_cs.transform(sdo_geometry(2001 ,4326 ,sdo_geom.sdo_point_type(-84, 0, NULL), NULL ,NULL),32616) FROM dual
    --------------
    (2001; 32616; (833978.556820659; 0; ); ; )
    
    SELECT sdo_geom.sdo_distance
    (sdo_geom.sdo_geometry(2001 ,32616 ,sdo_point_type(166021, 0, 0) ,NULL ,NULL),
      sdo_geom.sdo_geometry(2001 ,32616 ,sdo_point_type(833978, 0, 0) ,NULL ,NULL)
      ,0.0001 ,'unit=KM') distance_in_m
      FROM DUAL;
    --------------
    667,957
    
  • Find the minimum distance between two SDO_GEOMETRY in Oracle Spatial?

    annular ring edit.png

    A circle (SDO_GEOMETRY)
    B - polygon (SDO_GEOMETRY)

    CASE:
    B contains A (or)
    The Interior of B.

    How to find the minimum distance between A and B in Oracle Spatial

    Hello guuid nameless person.

    What is

    my_answer := MDSYS.SDO_GEOM.SDO_DISTANCE(
       my_circle_geometry
      ,MDSYS.SDO_UTIL.POLYGONTOLINE(my_outer_polygon)
      ,my_tolerance
    );
    

    Now, you may need to pay attention to the holes in your polygon, would you the distance and an inner ring if it was closer to you?

    If the measure is only to outer rings, so something like

    my_answer := MDSYS.SDO_GEOM.SDO_DISTANCE(
       my_circle_geometry
      ,MDSYS.SDO_UTIL.POLYGONTOLINE(
          MDSYS.SDO_UTIL.EXTRACT(my_outer_polygon,1,1)
       )
      ,my_tolerance
    );
    

    And then also beware of the multipolygons as the foregoing only measured against the first polygon in the MultiPolygon.  You need to loop through the polygons of tests just the outer ring in this case.

    See you soon,.

    Paul

  • Problems with validation

    I went from one ploygon is and I'm now getting a validation error. The error is 13351 indicating the crossing, but makes no sense since the geometry has changed only to become bigger. No changes were made to the difference between the ring and the polygon.

    -Geometry valid

    POLYGON ((-135.0 30,5,-134.99185 30.041386,-134.98405 30.034086,-134.95401 30.005964,-134.94765 30,0,-133.5 30,0,-133.5 30,5,-135.0 30,5), (-134.14302 30.005978,-134.15857 30.006021 - 134.1741 30.006367-, 134.18962 30.007006 - 134.20514 30.00795-, 134.22061 30.009184 - 134.23605 30.010723-, 30.012556 - 134.2668 30.014683 - 134.25145, 134.28804 30.019129 - 134.3007 30.02694-, 30.036272 - 134.32144 30.046923 - 134.31192, 134.32907 30.05866 - 134.33464 30.071234-, 30.084389 - 134.33902 30.097822 - 134.33798, 134.33699 30.111183 - 134.33412 30.124422-, 30.1375 - 134.3264 30.1505 - 134.33043, 134.32031 30.162872)) ,-134.31268 30.174572 - 134.30228 30.184523-, 134.28958 30.192234 - 134.27316 30.1978-, 134.228 30.207745 - 134.1761 30.2131-, 134.12085 30.212633 - 134.04973 30.202162-, 133.9964 30.189205 - 133.9541 30.17085-, 133.9415 30.162994 - 133.9309 30.153177-, 133.92265 30.141773 - 133.91707 30.129238-, 133.91539 30.115883 - 133.91785 30.102583-, 133.92172 30.089539 - 133.92686 30.076834-, 133.9339 30.064833 - 133.94272 30.053745-, 30.043777 - 133.96469 30.034756 - 133.95316, 133.97697 30.026539 - 133.9909 30.0206-, 30.016367 - 134.03474 30.014029 - 134.01944, 134.0501 30.01199 - 134.0655 30.010244-, 30.008795 - 134.09645 30.007645 - 134.08096, 134.11195 30.006788-134.12749 30.006233 (,-134.14302 30.005978))


    -Invalid geometry, (only differences is polygon is shifted is)

    POLYGON ((-135.0 30,5,-134.99185 30.041386,-134.98405 30.034086,-134.95401 30.005964,-134.94765 30,0,-132.0 30,0,-132.0 30,5,-135.0 30,5), (-134.14302 30.005978,-134.15857 30.006021 - 134.1741 30.006367-, 134.18962 30.007006 - 134.20514 30.00795-, 134.22061 30.009184 - 134.23605 30.010723-, 30.012556 - 134.2668 30.014683 - 134.25145, 134.28804 30.019129 - 134.3007 30.02694-, 30.036272 - 134.32144 30.046923 - 134.31192, 134.32907 30.05866 - 134.33464 30.071234-, 30.084389 - 134.33902 30.097822 - 134.33798, 134.33699 30.111183 - 134.33412 30.124422-, 30.1375 - 134.3264 30.1505 - 134.33043, 134.32031 30.162872)) ,-134.31268 30.174572 - 134.30228 30.184523-, 134.28958 30.192234 - 134.27316 30.1978-, 134.228 30.207745 - 134.1761 30.2131-, 134.12085 30.212633 - 134.04973 30.202162-, 133.9964 30.189205 - 133.9541 30.17085-, 133.9415 30.162994 - 133.9309 30.153177-, 133.92265 30.141773 - 133.91707 30.129238-, 133.91539 30.115883 - 133.91785 30.102583-, 133.92172 30.089539 - 133.92686 30.076834-, 133.9339 30.064833 - 133.94272 30.053745-, 30.043777 - 133.96469 30.034756 - 133.95316, 133.97697 30.026539 - 133.9909 30.0206-, 30.016367 - 134.03474 30.014029 - 134.01944, 134.0501 30.01199 - 134.0655 30.010244-, 30.008795 - 134.09645 30.007645 - 134.08096, 134.11195 30.006788-134.12749 30.006233 (,-134.14302 30.005978))

    Hello the number of name-less 1064020,

    Oracle spatial determines the validity of your GEODESIC geometry on the sphere, not a flat surface.  So in your original geometry that is large enough, the distance between the hole and the outer edge is only 447 meters.  As stretch you the outer ring of the geometry (you will double the size of it) of the lower edge of geometry "hiking upward" along the curve of the Earth.  However, the hole is anchored by many peaks to be where you placed it.  So, there's a point where they begin to cross.

    This is the measure of the gap before and after your stretching.

    WITH geometries AS (
      SELECT
        MDSYS.SDO_UTIL.POLYGONTOLINE(MDSYS.SDO_UTIL.EXTRACT(a.original,1,1))  AS original_outer
      ,MDSYS.SDO_UTIL.POLYGONTOLINE(MDSYS.SDO_UTIL.EXTRACT(a.original,1,2))  AS original_hole
      ,MDSYS.SDO_UTIL.POLYGONTOLINE(MDSYS.SDO_UTIL.EXTRACT(a.stretched,1,1)) AS stretched_outer
      ,MDSYS.SDO_UTIL.POLYGONTOLINE(MDSYS.SDO_UTIL.EXTRACT(a.stretched,1,2)) AS stretched_hole
      FROM (
          SELECT
          MDSYS.SDO_GEOMETRY('POLYGON ((-135.0 30.5,-134.99185 30.041386,-134.98405 30.034086,-134.95401 30.005964,-134.94765 30.0,-133.5 30.0,-133.5 30.5, -135.0 30.5),( -134.14302 30.005978,-134.15857 30.006021,-134.1741 30.006367,-134.18962 30.007006,-134.20514 30.00795,-134.22061 30.009184,-134.23605 30.010723,-134.25145 30.012556,-134.2668 30.014683,-134.28804 30.019129,-134.3007 30.02694,-134.31192 30.036272,-134.32144 30.046923,-134.32907 30.05866,-134.33464 30.071234,-134.33798 30.084389,-134.33902 30.097822,-134.33699 30.111183,-134.33412 30.124422,-134.33043 30.1375,-134.3264 30.1505,-134.32031 30.162872,-134.31268 30.174572,-134.30228 30.184523,-134.28958 30.192234,-134.27316 30.1978,-134.228 30.207745,-134.1761 30.2131,-134.12085 30.212633,-134.04973 30.202162,-133.9964 30.189205,-133.9541 30.17085,-133.9415 30.162994,-133.9309 30.153177,-133.92265 30.141773,-133.91707 30.129238,-133.91539 30.115883,-133.91785 30.102583,-133.92172 30.089539,-133.92686 30.076834,-133.9339 30.064833,-133.94272 30.053745,-133.95316 30.043777,-133.96469 30.034756,-133.97697 30.026539,-133.9909 30.0206,-134.01944 30.016367,-134.03474 30.014029,-134.0501 30.01199,-134.0655 30.010244,-134.08096 30.008795,-134.09645 30.007645,-134.11195 30.006788,-134.12749 30.006233,-134.14302 30.005978))',8265) AS original
          ,MDSYS.SDO_GEOMETRY('POLYGON ((-135.0 30.5,-134.99185 30.041386,-134.98405 30.034086,-134.95401 30.005964,-134.94765 30.0,-132.0 30.0,-132.0 30.5, -135.0 30.5),( -134.14302 30.005978,-134.15857 30.006021,-134.1741 30.006367,-134.18962 30.007006,-134.20514 30.00795,-134.22061 30.009184,-134.23605 30.010723,-134.25145 30.012556,-134.2668 30.014683,-134.28804 30.019129,-134.3007 30.02694,-134.31192 30.036272,-134.32144 30.046923,-134.32907 30.05866,-134.33464 30.071234,-134.33798 30.084389,-134.33902 30.097822,-134.33699 30.111183,-134.33412 30.124422,-134.33043 30.1375,-134.3264 30.1505,-134.32031 30.162872,-134.31268 30.174572,-134.30228 30.184523,-134.28958 30.192234,-134.27316 30.1978,-134.228 30.207745,-134.1761 30.2131,-134.12085 30.212633,-134.04973 30.202162,-133.9964 30.189205,-133.9541 30.17085,-133.9415 30.162994,-133.9309 30.153177,-133.92265 30.141773,-133.91707 30.129238,-133.91539 30.115883,-133.91785 30.102583,-133.92172 30.089539,-133.92686 30.076834,-133.9339 30.064833,-133.94272 30.053745,-133.95316 30.043777,-133.96469 30.034756,-133.97697 30.026539,-133.9909 30.0206,-134.01944 30.016367,-134.03474 30.014029,-134.0501 30.01199,-134.0655 30.010244,-134.08096 30.008795,-134.09645 30.007645,-134.11195 30.006788,-134.12749 30.006233,-134.14302 30.005978))',8265) AS stretched
          FROM
          dual
      ) a
    )
    SELECT
    MDSYS.SDO_GEOM.SDO_DISTANCE(a.original_outer,a.original_hole,0.05) AS original_gap
    ,MDSYS.SDO_GEOM.SDO_DISTANCE(a.stretched_outer,a.stretched_hole,0.05) AS stretched_gap
    FROM
    geometries a;
    

    If you wish to change your geometries in this way, you must use a projected coordinate system.  You can also simply densify your GEODESIC geometry by adding more points along the long edges of the polygon.

    This happens from time to time on the forum, I searched on a good explanation online but couldn't find something simple.  Someone else has a link to 1064020?

    See you soon,.

    Paul

  • sdo_within_distance return invalid results

    I use sdo_within_distance, and I notice that there are cases where results contain geometries that are outside the distance, I said. In the example below, the geometry is returned even if it is 4 miles from the reference geometry. If I use sdo_nn with the remote setting, the correct results are returned. DB version is 12.1.0.1.0

    Create the table testdistance

    (

    Identification number,

    geom sdo_geometry

    );

    Insert into testdistance (ID, GEOM) values (1, MDSYS. SDO_GEOMETRY (2001,4326, MDSYS. SDO_POINT_TYPE(-117.234313964844,32.7089462280273,), NULL, NULL));

    Insert into testdistance (ID, GEOM) values (477488906, MDSYS. SDO_GEOMETRY (2003,4326, NULL, MDSYS. SDO_ELEM_INFO_ARRAY (1,1003,1), MDSYS. SDO_ORDINATE_ARRAY(-117.175918579102,32.6773681640625,-117.17529296875,32.6780090332031,-117.174987792969,32.6778030395508,-117.17561340332,32.6771392822266,-117.175918579102,32.6773681640625)));

    insert into (table_name, column_name, diminfo, srid) user_sdo_geom_metadata

    values ('TESTDISTANCE', "GEOM", MDSYS. SDO_DIM_ARRAY (MDSYS. SDO_DIM_ELEMENT ('Longitude',-180, 180, 0.05), MDSYS. SDO_DIM_ELEMENT('Latitude',-90,90,0.05)), 4326);

    create index testdistance_sidx on testdistance (geom) INDEXTYPE IS MDSYS. SPATIAL_INDEX;

    -results of evil

    WITH the entry INTO

    (SELECT / * + materialize * / idgeom )

    OF testdistance

    ID WHERE = 1

    )

    SELECT / * + index (testdistance, testdistance_sidx) * / testdistance.id, testdistance.geom, sdo_geom.sdo_distance (testdistance.geom, input.geom, 0.05, ' unit = mile') dist

    Testdistance entry

    WHERE sdo_within_distance (testdistance.geom, input.geom, 'distance = 2.5 unit = mile') = 'TRUE '.

    -correct results

    WITH the entry INTO

    (SELECT / * + materialize * / idgeom )

    OF testdistance

    ID WHERE = 1

    )

    SELECT / * + index (testdistance, testdistance_sidx) * / testdistance.id, testdistance.geomSDO_NN_DISTANCE (1) dist

    Testdistance entry

    WHERE sdo_nn (testdistance.geom, input.geom, 'distance = 2.5 thousand = unit', 1) = "TRUE".

    Geometry with id = 477488906 is not valid because its outer ring is

    in a clockwise direction. You can use the following query to check them.

    Select sdo_geom.validate_geometry (geom, 0.05), id testdistance;

    Once the geometry with id = 477488906 is corrected (e.g. using sdo_util.rectify_geometry),

    the result of sdo_within_distance() should be good.

  • How gaps (fill) when converting to a 2006 geometry in a geometry of 2002

    Is it possible to fill (filling) the differences when converting to a geometry in a single geometry of 2002 in 2006. I have a solution for the conversion of 2006 to 2002 provided by BHall but on other investigation of my dataset some of the multi line polygons are weak I need to fill and I don't know how to go on this subject.

    Here is a simple example of what I'm trying to reach

    Front

    SELECT (sdo_geometry (2006, 81989, NULL,))

    MDSYS.sdo_elem_info_array (1,2,1,5,2,1,9,2,1,13,2,1),

    MDSYS.sdo_ordinate_array (16,0.999,16.998,-0,001, 17.253,-0.001, 18.003, 0.999, 18.003, 0.999, 19.001, 0.999, 19.001, 0.999, 19,999,-0,001)))

    OF the double

    After

    SELECT (sdo_geometry (2006, 81989, NULL,))

    MDSYS.sdo_elem_info_array (1,2,1),

    MDSYS.sdo_ordinate_array (16,0.999,17.253,-0.001,18.003,0.999,19.001,0.999,19.999,-0.001))) DOUBLE

    Thanks in advance

    Hi rock,

    Well, I ran all three examples that you sent through my code and it seemed to work!  I pasted the code above in a "pre" html tag and I can still see things deteriorated.  Lemme try this with a different syntax.  You know that this new forum software not only grew on me.  It's just clumsy and exaggerated.  And those weird people at the top.  What were they looking at?  I imagine that Larry on some loft above.

    Anyway, you are right that when Bryan code is used to convert the multiple string, the gaps are filled.  But that's because he wrote of this approach.

    Really, there is no generic way to convert a multiple line string we are discussing.  If you use SDO_UTIL. CONCATENATE_LINES, it will leave gaps.

    See you soon,.

    Paul

    CREATE OR REPLACE PACKAGE dz_gap_fill
    AUTHID CURRENT_USER
    AS
    
       FUNCTION linear_gap_filler(
           p_input            IN  MDSYS.SDO_GEOMETRY
          ,p_tolerance        IN  NUMBER DEFAULT 0.05
       ) RETURN MDSYS.SDO_GEOMETRY;
    
    END dz_gap_fill;
    
    CREATE OR REPLACE PACKAGE BODY dz_gap_fill
    AS
    
       FUNCTION fast_point(
           p_x             IN  NUMBER
          ,p_y             IN  NUMBER
          ,p_z             IN  NUMBER DEFAULT NULL
          ,p_m             IN  NUMBER DEFAULT NULL
          ,p_srid          IN  NUMBER DEFAULT 8265
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
       BEGIN
    
          --------------------------------------------------------------------------
          -- Step 10
          -- Check over incoming parameters
          --------------------------------------------------------------------------
          IF p_x IS NULL
          OR p_y IS NULL
          THEN
             RAISE_APPLICATION_ERROR(-20001,'x and y cannot be NULL');
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 20
          -- Do the simplest solution first
          --------------------------------------------------------------------------
          IF  p_z IS NULL
          AND p_m IS NULL
          THEN
             RETURN SDO_GEOMETRY(
                 2001
                ,p_srid
                ,SDO_POINT_TYPE(
                     p_x
                    ,p_y
                    ,NULL
                 )
                ,NULL
                ,NULL
             );
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 30
          -- Do the other wilder choices
          --------------------------------------------------------------------------
          IF p_z IS NULL
          AND p_m IS NOT NULL
          THEN
             RETURN SDO_GEOMETRY(
                 3301
                ,p_srid
                ,SDO_POINT_TYPE(
                     p_x
                    ,p_y
                    ,p_m
                 )
                ,NULL
                ,NULL
             );
    
          ELSIF p_z IS NOT NULL
          AND   p_m IS NULL
          THEN
             RETURN SDO_GEOMETRY(
                 3001
                ,p_srid
                ,SDO_POINT_TYPE(
                     p_x
                    ,p_y
                    ,p_z
                 )
                ,NULL
                ,NULL
             );
    
          ELSIF p_z IS NOT NULL
          AND   p_m IS NOT NULL
          THEN
             RETURN SDO_GEOMETRY(
                 4401
                ,p_srid
                ,NULL
                ,SDO_ELEM_INFO_ARRAY(1,1,1)
                ,SDO_ORDINATE_ARRAY(p_x,p_y,p_z,p_m)
             );
    
          ELSE
             RAISE_APPLICATION_ERROR(-20001,'ERR!');
          END IF;
    
       END fast_point;
    
       FUNCTION get_start_point(
          p_input        IN  MDSYS.SDO_GEOMETRY
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
          int_dims PLS_INTEGER;
          int_gtyp PLS_INTEGER;
          int_lrs  PLS_INTEGER;
    
       BEGIN
    
          --------------------------------------------------------------------------
          -- Step 10
          -- Check over incoming parameters
          --------------------------------------------------------------------------
          IF p_input IS NULL
          THEN
             RETURN NULL;
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 20
          -- Gather information about the geometry
          --------------------------------------------------------------------------
          int_dims := p_input.get_dims();
          int_gtyp := p_input.get_gtype();
          int_lrs  := p_input.get_lrs_dim();
    
          --------------------------------------------------------------------------
          -- Step 30
          -- Handle point and multipoint inputs
          --------------------------------------------------------------------------
          IF int_gtyp = 1
          THEN
             RETURN p_input;
    
          ELSIF int_gtyp = 5
          THEN
             RETURN SDO_UTIL.EXTRACT(p_input,1);
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 40
          -- Return results
          --------------------------------------------------------------------------
          IF int_dims = 2
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(1)
                ,p_input.SDO_ORDINATES(2)
                ,NULL
                ,NULL
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 3
          AND int_lrs = 3
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(1)
                ,p_input.SDO_ORDINATES(2)
                ,NULL
                ,p_input.SDO_ORDINATES(3)
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 3
          AND int_lrs = 0
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(1)
                ,p_input.SDO_ORDINATES(2)
                ,p_input.SDO_ORDINATES(3)
                ,NULL
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 4
          AND int_lrs IN (4,0)
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(1)
                ,p_input.SDO_ORDINATES(2)
                ,p_input.SDO_ORDINATES(3)
                ,p_input.SDO_ORDINATES(4)
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 4
          AND int_lrs = 3
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(1)
                ,p_input.SDO_ORDINATES(2)
                ,p_input.SDO_ORDINATES(4)
                ,p_input.SDO_ORDINATES(3)
                ,p_input.SDO_SRID
             );
    
          ELSE
             RAISE_APPLICATION_ERROR(-20001,'ERR!');
    
          END IF;
    
       END get_start_point;
    
       FUNCTION get_end_point(
          p_input        IN  MDSYS.SDO_GEOMETRY
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
          int_dims PLS_INTEGER;
          int_gtyp PLS_INTEGER;
          int_lrs  PLS_INTEGER;
          int_len  PLS_INTEGER;
    
       BEGIN
    
          --------------------------------------------------------------------------
          -- Step 10
          -- Check over incoming parameters
          --------------------------------------------------------------------------
          IF p_input IS NULL
          THEN
             RETURN NULL;
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 20
          -- Gather information about the geometry
          --------------------------------------------------------------------------
          int_dims := p_input.get_dims();
          int_gtyp := p_input.get_gtype();
          int_lrs  := p_input.get_lrs_dim();
          int_len  := p_input.SDO_ORDINATES.COUNT();
    
          --------------------------------------------------------------------------
          -- Step 30
          -- Handle point and multipoint inputs
          --------------------------------------------------------------------------
          IF int_gtyp = 1
          THEN
             RETURN p_input;
          ELSIF int_gtyp = 5
          THEN
             RETURN SDO_UTIL.EXTRACT(
                 p_input
                ,SDO_UTIL.GETNUMELEM(p_input)
             );
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 40
          -- Return results
          --------------------------------------------------------------------------
          IF int_dims = 2
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(int_len - 1)
                ,p_input.SDO_ORDINATES(int_len)
                ,NULL
                ,NULL
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 3
          AND int_lrs = 3
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(int_len - 2)
                ,p_input.SDO_ORDINATES(int_len - 1)
                ,NULL
                ,p_input.SDO_ORDINATES(int_len)
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 3
          AND int_lrs = 0
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(int_len - 2)
                ,p_input.SDO_ORDINATES(int_len - 1)
                ,p_input.SDO_ORDINATES(int_len)
                ,NULL
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 4
          AND int_lrs IN (4,0)
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(int_len - 3)
                ,p_input.SDO_ORDINATES(int_len - 2)
                ,p_input.SDO_ORDINATES(int_len - 1)
                ,p_input.SDO_ORDINATES(int_len)
                ,p_input.SDO_SRID
             );
    
          ELSIF  int_dims = 4
          AND int_lrs = 3
          THEN
             RETURN fast_point(
                 p_input.SDO_ORDINATES(int_len - 3)
                ,p_input.SDO_ORDINATES(int_len - 2)
                ,p_input.SDO_ORDINATES(int_len)
                ,p_input.SDO_ORDINATES(int_len - 1)
                ,p_input.SDO_SRID
             );
    
          ELSE
             RAISE_APPLICATION_ERROR(-20001,'ERR!');
    
          END IF;
    
       END get_end_point;
    
       FUNCTION is_spaghetti(
           p_input             IN  MDSYS.SDO_GEOMETRY
          ,p_tolerance         IN  NUMBER DEFAULT 0.05
       ) RETURN VARCHAR2
       AS
          num_tolerance    NUMBER := p_tolerance;
          ary_strings      MDSYS.SDO_GEOMETRY_ARRAY := MDSYS.SDO_GEOMETRY_ARRAY();
          ary_starts       MDSYS.SDO_GEOMETRY_ARRAY := MDSYS.SDO_GEOMETRY_ARRAY();
          ary_ends         MDSYS.SDO_GEOMETRY_ARRAY := MDSYS.SDO_GEOMETRY_ARRAY();
          int_count        PLS_INTEGER;
          ary_start_count  MDSYS.SDO_NUMBER_ARRAY := MDSYS.SDO_NUMBER_ARRAY();
          ary_end_count    MDSYS.SDO_NUMBER_ARRAY := MDSYS.SDO_NUMBER_ARRAY();
          ary_inside_count MDSYS.SDO_NUMBER_ARRAY := MDSYS.SDO_NUMBER_ARRAY();
    
       BEGIN
    
          --------------------------------------------------------------------------
          -- Step 10
          -- Check over incoming parameters
          --------------------------------------------------------------------------
          IF p_input IS NULL
          THEN
             RETURN NULL;
    
          ELSIF p_input.get_gtype = 2
          THEN
             RETURN 'FALSE';
    
          ELSIF p_input.get_gtype <> 6
          THEN
             RAISE_APPLICATION_ERROR(-20001,'input gtype must be 2 or 6');
    
          END IF;
    
          IF num_tolerance IS NULL
          THEN
             num_tolerance := 0.05;
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 20
          -- Break multistring into single linestrings with nodes
          --------------------------------------------------------------------------
          int_count := SDO_UTIL.GETNUMELEM(p_input);
          ary_strings.EXTEND(int_count);
          ary_starts.EXTEND(int_count);
          ary_ends.EXTEND(int_count);
          ary_start_count.EXTEND(int_count);
          ary_end_count.EXTEND(int_count);
          ary_inside_count.EXTEND(int_count);
          FOR i IN 1 .. int_count
          LOOP
             ary_strings(i) := SDO_UTIL.EXTRACT(p_input,i);
             ary_starts(i)  := get_start_point(ary_strings(i));
             ary_ends(i)    := get_end_point(ary_strings(i));
    
          END LOOP;
    
          --------------------------------------------------------------------------
          -- Step 30
          -- Loop through and count the nodes connections
          --------------------------------------------------------------------------
          FOR i IN 1 .. int_count
          LOOP
             ary_start_count(i)  := 0;
             ary_end_count(i)    := 0;
             ary_inside_count(i) := 0;
    
             FOR j IN 1 .. int_count
             LOOP
                IF i != j
                THEN
                   IF SDO_GEOM.RELATE(
                      ary_starts(i),
                      'DETERMINE',
                      ary_strings(j),
                      num_tolerance
                   ) IN ('TOUCH','CONTAINS','COVERS','ON')
                   THEN
                      ary_start_count(i) := ary_start_count(i) + 1;
    
                   ELSIF SDO_GEOM.RELATE(
                      ary_ends(i),
                      'DETERMINE',
                      ary_strings(j),
                      num_tolerance
                   ) IN ('TOUCH','CONTAINS','COVERS','ON')
                   THEN
                      ary_end_count(i) := ary_end_count(i) + 1;
    
                   ELSIF SDO_GEOM.RELATE(
                      ary_strings(i),
                      'DETERMINE',
                      ary_strings(j),
                      num_tolerance
                   ) IN ('TOUCH','CONTAINS','COVERS','OVERLAPBYINTERSECT')
                   THEN
                      ary_inside_count(i) := ary_inside_count(i) + 1;
    
                   END IF;
    
                END IF;
    
             END LOOP;
    
             IF ary_start_count(i) > 1
             OR ary_end_count(i) > 1
             OR ary_inside_count(i) > 0
             THEN
                RETURN 'TRUE';
             END IF;
    
          END LOOP;
    
          RETURN 'FALSE';
    
       END is_spaghetti;
    
       -----------------------------------------------------------------------------
       -----------------------------------------------------------------------------
       FUNCTION points2segment(
           p_point_one              IN  MDSYS.SDO_POINT_TYPE
          ,p_point_two              IN  MDSYS.SDO_POINT_TYPE
          ,p_srid                   IN  NUMBER
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
       BEGIN
    
          IF ( p_point_one.Z IS NULL AND p_point_two.Z IS NOT NULL )
          OR ( p_point_one.Z IS NOT NULL AND p_point_two.Z IS NULL )
          THEN
             RAISE_APPLICATION_ERROR(
                -20001,
                'both points must have the same number of dimensions, point_one Z is ' ||
                NVL(TO_CHAR(p_point_one.Z),'') ||
                ' and point_two Z is ' ||
                NVL(TO_CHAR(p_point_two.Z),'')
             );
    
          END IF;
    
          IF p_point_one.Z IS NULL
          THEN
             RETURN SDO_GEOMETRY(
                 2002
                ,p_srid
                ,NULL
                ,SDO_ELEM_INFO_ARRAY(1,2,1)
                ,SDO_ORDINATE_ARRAY(p_point_one.X,p_point_one.Y,p_point_two.X,p_point_two.Y)
             );
    
          ELSE
             RETURN SDO_GEOMETRY(
                 3002
                ,p_srid
                ,NULL
                ,SDO_ELEM_INFO_ARRAY(1,2,1)
                ,SDO_ORDINATE_ARRAY(p_point_one.X,p_point_one.Y,p_point_one.Z,p_point_two.X,p_point_two.Y,p_point_two.Z)
             );
    
          END IF;
    
       END points2segment;
    
       -----------------------------------------------------------------------------
       -----------------------------------------------------------------------------
       FUNCTION points2segment(
           p_point_one              IN  MDSYS.SDO_GEOMETRY
          ,p_point_two              IN  MDSYS.SDO_GEOMETRY
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
          int_gtype1 PLS_INTEGER;
          int_dims1  PLS_INTEGER;
          int_gtype2 PLS_INTEGER;
          int_dims2  PLS_INTEGER;
          point_one  MDSYS.SDO_POINT_TYPE;
          point_two  MDSYS.SDO_POINT_TYPE;
    
       BEGIN
    
          int_gtype1 := p_point_one.get_gtype();
          int_dims1  := p_point_one.get_dims();
          int_gtype2 := p_point_two.get_gtype();
          int_dims2  := p_point_two.get_dims();
    
          IF  int_gtype1 = 1
          AND int_gtype2 = 1
          AND int_dims1  = int_dims2
          AND p_point_one.SDO_SRID = p_point_two.SDO_SRID
          THEN
             NULL;  -- Good
    
          ELSE
             RAISE_APPLICATION_ERROR(
                 -20001
                ,'both point objects must be points and have the same number of dimensions and SRIDs'
             );
    
          END IF;
    
          IF int_dims1 = 4
          THEN
             RETURN SDO_GEOMETRY(
                 4402
                ,p_point_one.SDO_SRID
                ,NULL
                ,SDO_ELEM_INFO_ARRAY(1,2,1)
                ,SDO_ORDINATE_ARRAY(
                     p_point_one.SDO_ORDINATES(1)
                    ,p_point_one.SDO_ORDINATES(2)
                    ,p_point_one.SDO_ORDINATES(3)
                    ,p_point_one.SDO_ORDINATES(4)
                    ,p_point_two.SDO_ORDINATES(1)
                    ,p_point_two.SDO_ORDINATES(2)
                    ,p_point_two.SDO_ORDINATES(3)
                    ,p_point_two.SDO_ORDINATES(4)
                )
             );
    
          ELSE
             -- Use the sdo_point_type method for the rest
             IF p_point_one.SDO_POINT IS NOT NULL
             THEN
                point_one := p_point_one.SDO_POINT;
    
             ELSE
                IF int_dims1 = 3
                THEN
                   point_one := SDO_POINT_TYPE(
                       p_point_one.SDO_ORDINATES(1)
                      ,p_point_one.SDO_ORDINATES(2)
                      ,p_point_one.SDO_ORDINATES(3)
                   );
    
                ELSE
                   point_one := SDO_POINT_TYPE(
                       p_point_one.SDO_ORDINATES(1)
                      ,p_point_one.SDO_ORDINATES(2)
                      ,NULL
                   );
    
                END IF;
    
             END IF;
    
             IF p_point_two.SDO_POINT IS NOT NULL
             THEN
                point_two := p_point_two.SDO_POINT;
    
             ELSE
                IF int_dims1 = 3
                THEN
                   point_two := SDO_POINT_TYPE(
                        p_point_two.SDO_ORDINATES(1)
                       ,p_point_two.SDO_ORDINATES(2)
                       ,p_point_two.SDO_ORDINATES(3)
                   );
    
                ELSE
                   point_two := SDO_POINT_TYPE(
                       p_point_two.SDO_ORDINATES(1)
                      ,p_point_two.SDO_ORDINATES(2)
                      ,NULL
                   );
    
                END IF;
    
             END IF;
    
             RETURN points2segment(
                 p_point_one   => point_one
                ,p_point_two   => point_two
                ,p_srid        => p_point_one.SDO_SRID
             );
    
          END IF;
    
       END points2segment;
    
       FUNCTION linear_gap_filler(
           p_input            IN  MDSYS.SDO_GEOMETRY
          ,p_tolerance        IN  NUMBER DEFAULT 0.05
       ) RETURN MDSYS.SDO_GEOMETRY
       AS
          sdo_input     MDSYS.SDO_GEOMETRY := p_input;
          num_tolerance NUMBER;
          int_counter   PLS_INTEGER;
          ary_edges     MDSYS.SDO_GEOMETRY_ARRAY;
          ary_starts    MDSYS.SDO_GEOMETRY_ARRAY;
          ary_ends      MDSYS.SDO_GEOMETRY_ARRAY;
          ary_nearest   MDSYS.SDO_NUMBER_ARRAY;
          ary_distance  MDSYS.SDO_NUMBER_ARRAY;
          num_temp      NUMBER;
          num_nearest   NUMBER;
          int_winner    PLS_INTEGER;
          int_winner2   PLS_INTEGER;
          sdo_point1    MDSYS.SDO_GEOMETRY;
          sdo_point2    MDSYS.SDO_GEOMETRY;
          boo_done      BOOLEAN;
          num_one       NUMBER;
          num_two       NUMBER;
          int_looper    PLS_INTEGER := 1;
    
       BEGIN
    
          --------------------------------------------------------------------------
          -- Step 10
          -- Check over incoming parameters
          --------------------------------------------------------------------------
          IF num_tolerance IS NULL
          THEN
             num_tolerance := 0.05;
    
          END IF;
    
          IF sdo_input IS NULL
          OR sdo_input.get_gtype() <> 6
          THEN
             RETURN sdo_input;
    
          END IF;
    
          IF is_spaghetti(sdo_input,p_tolerance) = 'TRUE'
          THEN
             RETURN sdo_input;
    
          END IF;
    
          <>
          ary_edges     := MDSYS.SDO_GEOMETRY_ARRAY();
          ary_starts    := MDSYS.SDO_GEOMETRY_ARRAY();
          ary_ends      := MDSYS.SDO_GEOMETRY_ARRAY();
          ary_nearest   := MDSYS.SDO_NUMBER_ARRAY();
          ary_distance  := MDSYS.SDO_NUMBER_ARRAY();
    
          --------------------------------------------------------------------------
          -- Step 20
          -- Break multistring into edges and start and end nodes
          --------------------------------------------------------------------------
          int_counter := SDO_UTIL.GETNUMELEM(sdo_input);
          ary_edges.EXTEND(int_counter);
          ary_starts.EXTEND(int_counter);
          ary_ends.EXTEND(int_counter);
          FOR i IN 1 .. int_counter
          LOOP
             ary_edges(i)  := SDO_UTIL.EXTRACT(sdo_input,i);
             ary_starts(i) := get_start_point(ary_edges(i));
             ary_ends(i)   := get_end_point(ary_edges(i));
    
          END LOOP;
    
          --------------------------------------------------------------------------
          -- Step 30
          -- Determine the closest endpoints
          --------------------------------------------------------------------------
          ary_nearest.EXTEND(int_counter);
          ary_distance.EXTEND(int_counter);
          FOR i IN 1 .. int_counter
          LOOP
             num_nearest := NULL;
             int_winner := NULL;
             FOR j IN 1 .. int_counter
             LOOP
                IF j != i
                THEN
                   num_temp := SDO_GEOM.SDO_DISTANCE(
                       ary_edges(i)
                      ,ary_edges(j)
                      ,num_tolerance
                   );
    
                   IF num_nearest IS NULL
                   OR num_temp < num_nearest
                   THEN
                      num_nearest := num_temp;
                      int_winner := j;
    
                   END IF;
    
                END IF;
    
             END LOOP;
    
             ary_nearest(i) := int_winner;
             ary_distance(i) := num_nearest;
    
          END LOOP;
    
          --------------------------------------------------------------------------
          -- Step 40
          -- Find the smallest gap
          --------------------------------------------------------------------------
          int_winner := NULL;
          num_nearest := NULL;
          FOR i IN 1 .. int_counter
          LOOP
             IF num_nearest IS NULL
             OR ary_distance(i) < num_nearest
             THEN
                 int_winner := i;
                 num_nearest := ary_distance(i);
                 int_winner2 := ary_nearest(i);
    
             END IF;
    
          END LOOP;
    
          --------------------------------------------------------------------------
          -- Step 50
          -- Determine the endpoints to connect
          --------------------------------------------------------------------------
          num_one := SDO_GEOM.SDO_DISTANCE(
             get_start_point(ary_edges(int_winner)),
             ary_edges(int_winner2),
             num_tolerance
          );
          num_two := SDO_GEOM.SDO_DISTANCE(
             get_end_point(ary_edges(int_winner)),
             ary_edges(int_winner2),
             num_tolerance
          );
    
          IF ( num_one = 0 AND SDO_GEOM.RELATE(
             get_start_point(ary_edges(int_winner)),
             'ANYINTERACT',
             ary_edges(int_winner2),
             num_tolerance
          ) = 'TRUE' )
          OR ( num_two = 0 AND SDO_GEOM.RELATE(
             get_end_point(ary_edges(int_winner)),
             'ANYINTERACT',
             ary_edges(int_winner2),
             num_tolerance
          ) = 'TRUE' )
          THEN
             sdo_point1 := NULL;
    
          ELSIF num_one < num_two
          THEN
             sdo_point1 := get_start_point(ary_edges(int_winner));
    
          ELSE
             sdo_point1 := get_end_point(ary_edges(int_winner));
    
          END IF;
    
          num_one := SDO_GEOM.SDO_DISTANCE(
             get_start_point(ary_edges(int_winner2)),
             ary_edges(int_winner),
             num_tolerance
          );
          num_two := SDO_GEOM.SDO_DISTANCE(
             get_end_point(ary_edges(int_winner2)),
             ary_edges(int_winner),
             num_tolerance
          );
    
          IF ( num_one = 0 AND SDO_GEOM.RELATE(
             get_start_point(ary_edges(int_winner2)),
             'ANYINTERACT',
             ary_edges(int_winner),
             num_tolerance
          ) = 'TRUE' )
          OR ( num_two = 0 AND SDO_GEOM.RELATE(
             get_end_point(ary_edges(int_winner2)),
             'ANYINTERACT',
             ary_edges(int_winner),
             num_tolerance
          ) = 'TRUE' )
          THEN
             sdo_point2 := NULL;
    
          ELSIF num_one < num_two
          THEN
             sdo_point2 := get_start_point(ary_edges(int_winner2));
    
          ELSE
             sdo_point2 := get_end_point(ary_edges(int_winner2));
    
          END IF;
    
          --------------------------------------------------------------------------
          -- Step 50
          -- Smash together
          --------------------------------------------------------------------------
          IF sdo_point1 IS NULL
          OR sdo_point2 IS NULL
          THEN
             sdo_input := SDO_UTIL.CONCAT_LINES(
                ary_edges(int_winner),
                ary_edges(int_winner2)
             );
    
          ELSE
             sdo_input := SDO_UTIL.CONCAT_LINES(
                SDO_UTIL.CONCAT_LINES(
                   ary_edges(int_winner),
                   points2segment(sdo_point1,sdo_point2)
                ),
                ary_edges(int_winner2)
             );
    
          END IF;
    
          boo_done := TRUE;
          FOR i IN 1 .. int_counter
          LOOP
             IF i NOT IN (int_winner,int_winner2)
             THEN
                sdo_input := SDO_UTIL.APPEND(sdo_input,ary_edges(i));
                boo_done := FALSE;
    
             END IF;
    
          END LOOP;
    
          --------------------------------------------------------------------------
          -- Step 60
          -- Check if valid if returning
          --------------------------------------------------------------------------
          IF sdo_input.get_gtype() = 2
          OR boo_done = TRUE
          THEN
             RETURN sdo_input;
    
          END IF;
    
          int_looper := int_looper + 1;
          GOTO TOP_OF_IT;
    
       END linear_gap_filler;
    
    END dz_gap_fill;
    
  • nested to perform DML and wait function call commit

    Hello world

    I would like to make a few DML - one insert statement, to be precise - in function and have the function and then return the number keys on the newly added row. I call this function from a different context and woud then be able to use the newly added data to do something.

    Specifically, what I do is the following: I have a graph composed of triplets source, destination and distance in a picture. A user should now be able to

    1.) add a node "A" to the curve.
    2.) add a node 'B' to the chart
    (3.) to get the shortest path from A to B in the graphs.

    I have an internal function
    function INSERT_NEW_NODE(node_in in sdo_geometry, graph_in in integer) return integer
    is  
    
    pragma autonomous_transaction;
    
    cursor node_cur is  
      select 
          source,
          source_geom
      from graph  
    ;
        
    cursor edge_cur is
        select
            source,
            destination,
            distance,
            edge_geom
        from
          graph
        where
          sdo_geom.relate(edge_geom, 'anyinteract', node_in, .005) = 'TRUE';
    
    begin
    
      -- check if identical with any existing node
      for node_rec in node_cur loop  
        if sdo_geom.relate(node_rec.source_geom, 'EQUAL', node_in, .005) = 'EQUAL' then
          return node_rec.source;
        end if;
      end loop;    
      
      -- get edges
      for edge_rec in edge_cur loop
         -- new_node-->edge.destination and vice versa
        insert into
          graph
          (
            ID,
            GRAPH,
            SOURCE,
            DESTINATION,
            DISTANCE,
            SOURCE_GEOM,
            DESTINATION_GEOM,
            EDGE_GEOM
          )
        values
        (
          graph_id_seq.nextval, --id
          graph_in, --graph
          morton(node_in.sdo_point.x, node_in.sdo_point.y),  -- source morton key
          edge_rec.source, -- destination morton key
          sdo_geom.sdo_distance(edge_rec.source_geom_marl2000, node_in, .005, 'unit=M'), -- distance
          node_in, -- source geom
          edge_rec.source_geom,  -- dest geom
          split_line(edge_rec.edge_geom_marl2000, node_in).segment1 -- edge geom
        );
        commit;
        --new_node-->edge.source and vice versa
        insert into
          gl_graph
          (
            ID,
            GRAPH,
            SOURCE,
            DESTINATION,
            DISTANCE,
            SOURCE_GEOM,
            DESTINATION_GEOM,
            EDGE_GEOM
          )
        values
        (
          graph_id_seq.nextval, --id
          graph_in, --graph
          edge_rec.source, -- source morton key
          morton(node_in.sdo_point.x, node_in.sdo_point.y), -- destination morton key
          sdo_geom.sdo_distance(edge_rec.source_geom, node_in, .005, 'unit=M'), -- distance
          edge_rec.source_geom,  -- source geom
          node_in, -- dest geom
          split_line(edge_rec.edge_geom, node_in).segment2 -- edge geom
        );
        commit;
      end loop
      ;
     
      return(morton(node_in.sdo_point.x, node_in.sdo_point.y));
      
    end insert_new_node;
    adding new nodes to the chart, links, calculates distances etc. and returns a handle to the newly added node. I call this function twice function, external
    function get_path (line_in in sdo_geometry, graph_in in integer) return sdo_geometry
    is  
    
    source number;
    destination number;
    source_geom mdsys.sdo_geometry;
    destination_geom mdsys.sdo_geometry;
      
    begin
      
      source := insert_new_node(get_firstvertex(line_in), graph_in);
      destination := insert_new_node(get_lastvertex(line_in), graph_in);
     
      -- source := insert_new_node(get_firstvertex(line_in), graph_in);
      -- destination := insert_new_node(get_lastvertex(line_in), graph_in);
      
      return(get_path_geom(source, destination)); --returns a geometry which is the shortest path between source and destination
      
    end get_path;
    ; and I think thatI have to use autonomous transaction in the internal function, so that the external function can see any changes made by the inside one. However, it doesn't work, when I call twice the function internal (i.e. remove the comment panels in front of the last two lines of code just before the return statement in the outer function.)

    So here are my questions: 1) why should I call the function twice to see the complete transaction? (and 2.) How can I avoid this? Is it possible to wait for the execution of the return statement in the internal function that the insert is committed and can be seen by the external function?

    See you soon!

    OK, here's the solution: the external function get_path() calls a function get_path_geom(source, destination) , who himself called something like table(dijkstra(source, destination)) , (omitted by me because only carefully tested and ok, my bad!) which makes the job of finding the shortest path and returns an array in pipeline. It turns out that this feature for some reason is not the scope of the external function and therefore does not see the transaction committed themselves on the graphics table. After you change the dijkstra() -function to return a list instead of a table, all works all of a sudden.

    If this question has been answered; I would still like to know why the table function does not have the same scope as the rest of the transaction.

    Edit: removed misleading blame on application external and inserted a correct solution.

  • SDO_FILTER which gives weird results

    Hi people,

    Not sure if this is a bug or maybe I'm just not see something simple. On 11.2.0.4. I have an area of the area of interest and a line next door representing a piece of water, the two geometries validate the tolerance of 5 centimeters.
    http://www.dziemiela.com/june27.PNG
    The box is more than a mile away from the stream. The flow is relatively small and its MBR is no where close to touch the area. However, according to SDO_FILTER, two geometries are TRUE. I'm puzzled. So I wrote the mess for anyone wishing to give it a shot. I'll be back

    Streamy is valid? TRUE
    Véronique is valid? TRUE
    Basic SDO_GEOM. RELATE? DISJOINT
    Distance between 1795.19857225394 M
    MIL SDO_GEOM. RELATE? DISJOINT
    Distance between 1794.97512096382 M
    SDO_RELATE County 0
    SDO_FILTER County 1

    If two geometries are distance of 1.7 km and their members are distance of 1.7 km. I would like to say very clearly that these things shouldn't interact. Right? However, filter gives TRUE. Am I a something Klutz?

    Thank you
    Paul
    DECLARE
       sdo_streamy SDO_GEOMETRY := SDO_GEOMETRY(2002,8265,NULL,SDO_ELEM_INFO_ARRAY(1,2,1),SDO_ORDINATE_ARRAY(-77.6495001234516,38.9423350727726,-77.6482987901201,38.9418092727734,-77.6468049234557,38.9413522727742,-77.6461311901235,38.9413982061074,-77.6438177901271,38.942107872773,-77.6427925901286,38.9423368727726,-77.6423533234627,38.9422912727727,-77.6410643234647,38.9417884061068,-77.6406835234653,38.9416968727736,-77.6403321234658,38.9417886061068,-77.6394825901338,38.9417886727735,-77.63760792347,38.9414232061074,-77.6370221234709,38.9410114727747,-77.6357033901397,38.9392504727774,-77.6352933234736,38.9389760727778,-77.6347071901412,38.9380154727793,-77.6313675901464,38.9348822727842,-77.6301375234816,38.9342876061185,-77.6295517234825,38.9336930061194,-77.6294929901493,38.9335098727863));
       sdo_boxy SDO_GEOMETRY := SDO_GEOMETRY(2003,8265,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(-77.6087382736728,38.9295533233688,-77.4229814409148,38.9295533233688,-77.4229814409148,39.0744969598833,-77.6087382736728,39.0744969598833,-77.6087382736728,38.9295533233688));
       num_result NUMBER;
    BEGIN
       dbms_output.put_line('Streamy is valid? ' || SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(sdo_streamy,0.05));
       dbms_output.put_line('Boxy is valid? ' || SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(sdo_boxy,0.05));
       dbms_output.put_line('Basic SDO_GEOM.RELATE? ' || SDO_GEOM.RELATE(sdo_streamy,'DETERMINE',sdo_boxy,0.05));
       dbms_output.put_line('Distance Between ' || SDO_GEOM.SDO_DISTANCE(sdo_streamy,sdo_boxy,0.05) || 'M');
       dbms_output.put_line('MBRs SDO_GEOM.RELATE? ' || SDO_GEOM.RELATE(SDO_GEOM.SDO_MBR(sdo_streamy),'DETERMINE',SDO_GEOM.SDO_MBR(sdo_boxy),0.05));
       dbms_output.put_line('Distance Between ' || SDO_GEOM.SDO_DISTANCE(SDO_GEOM.SDO_MBR(sdo_streamy),SDO_GEOM.SDO_MBR(sdo_boxy),0.05) || 'M');
       EXECUTE IMMEDIATE 'CREATE TABLE streamy (shape SDO_GEOMETRY)';
       EXECUTE IMMEDIATE 'INSERT INTO streamy (shape) VALUES (:p01)' USING sdo_streamy; COMMIT;
       INSERT INTO user_sdo_geom_metadata(table_name,column_name,diminfo,srid) VALUES 
       ('STREAMY','SHAPE',MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,.05),MDSYS.SDO_DIM_ELEMENT('Y',-90,90,.05)),8265); COMMIT;
       EXECUTE IMMEDIATE 'CREATE INDEX streamy_spx ON streamy(shape) INDEXTYPE IS MDSYS.SPATIAL_INDEX';
       EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM streamy a WHERE SDO_RELATE(a.shape,:p01,''MASK=ANYINTERACT'')=''TRUE''' INTO num_result USING sdo_boxy;
       dbms_output.put_line('SDO_RELATE Count ' || TO_CHAR(num_result));
       EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM streamy a WHERE SDO_FILTER(a.shape,:p01)=''TRUE''' INTO num_result USING sdo_boxy;
       dbms_output.put_line('SDO_FILTER Count ' || TO_CHAR(num_result));
    END;
    /

    Hi Paul,.

    For geodetic geometry, R-tree index are in 3D. For example, you can see:

    SQL> select sdo_index_name, SDO_ROOT_MBR from user_sdo_index_metadata;
    
    SDO_INDEX_NAME
    --------------------------------
    SDO_ROOT_MBR(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINAT
    --------------------------------------------------------------------------------
    STREAMY_SPX
    SDO_GEOMETRY(3008, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1007, 3), SDO_ORDINATE_ARR
    AY(.16636, -.759816, .628418, .166646, -.759754, .628538))
    

    sdo_boxy is converted to:
    SDO_GEOMETRY (3008, NULL, NULL, SDO_ELEM_INFO_ARRAY (1, 1007, 3), SDO_ORDINATE_ARR)
    AY (. 166589,-. 759798,.628364,.169393,-. 757698,.630331))

    If the two MBR or minimum limit boxes (MBBs) intersect.

    Thank you
    Ying

  • How to create a polygon that covers a set of geometries?

    Hi people,

    I have a spatial table with the parcel data. Some are polygons and lines.
    What I have to do is to create a single polygon that covers all these plots.
    I tried some spatial functions, but the result is not perfect.
    Could you guys give some advice on how to do it using the Oracle Spatial functions?

    Thank you
    Luis

    Luis etc.,

    Delicate using the ST_PolygonBuilder (JTS) that implements my code SC4O Java-in-the-database and some coding, I managed to product a polygon that covers the data correctly.

    Note that I use only external linestrings which provides some Luis.

    -- First create a table holding only the outer lines.
    --
    create table outerLines as
      SELECT SDO_GEOMETRY(2002, 8292, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(-49.6878936628642, -18.4995538840232, -49.6875224063873, -18.4994400734344, -49.6882811644211, -18.4960292763006, -49.6886251490431, -18.4958803030445, -49.6906307026931, -18.4950115281619)) as geom from dual union all
      SELECT SDO_GEOMETRY(2002, 8292, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(-49.6884083531774, -18.4917625230274, -49.6886528151554, -18.4922451253898, -49.6898503241639, -18.4946091658756, -49.690098431643, -18.4950991112698, -49.6902068702432, -18.4950498009285, -49.6905958643821, -18.4948724904445)) as geom from dual union all
      SELECT SDO_GEOMETRY(2002, 8292, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(-49.6883413960309, -18.4918992292229, -49.6885491287687, -18.4923048595269, -49.6849860033691, -18.4934740072225, -49.6855427926656, -18.4945793006294, -49.6857982402423, -18.4950861997106, -49.6860079716291, -18.4955025995491, -49.6836133980005, -18.4962994912622, -49.6834396716227, -18.4957578264012)) as geom from dual union all
      SELECT SDO_GEOMETRY(2002, 8292, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(-49.6792385551751, -18.5000418095053, -49.6797119992317, -18.4998345697814, -49.6783397446724, -18.4980535328215, -49.6810365599698, -18.4971609552001, -49.6810385833744, -18.4971564511947, -49.6835051531636, -18.4963355157698, -49.6833312619652, -18.4958030666281)) as geom from dual union all
      SELECT SDO_GEOMETRY(2002, 8292, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(-49.6878678853177, -18.4996181336176, -49.6861731626715, -18.4991017919552, -49.6834080082784, -18.4982775371379, -49.6833583465082, -18.4983066497055, -49.6832975737928, -18.4983520405102, -49.6831594052426, -18.4984987309426, -49.6830586383606, -18.4986094463067, -49.6829994956301, -18.4986769870823, -49.6829194669485, -18.4987385992949, -49.6828337343539, -18.4987905933782, -49.6827167582476, -18.4988411048671, -49.6825978712605, -18.4988566328165, -49.6824876108137, -18.4988587567866, -49.6824343436196, -18.4988638980162, -49.6823495710101, -18.498901802054, -49.6820036074112, -18.4990727977958, -49.6815739264209, -18.4993045655044, -49.6815394467332, -18.4993194542279, -49.6815037571481, -18.4993313944568, -49.681467095582, -18.4993402576461, -49.6814297528519, -18.4993459734892, -49.6813920251781, -18.4993484966453, -49.6813542118344, -18.4993478070996, -49.6813166127745, -18.4993439103221, -49.6812795262518, -18.4993368372241, -49.6812432464542, -18.4993266439127, -49.6812080820875, -18.4993134018902, -49.6793284309429, -18.5001537628556)) as geom from dual;
    
    -- Firstly, fill in the gaps between all the outer lines by generating small 2 point linestrings....
    -- This is what the CTE, connected_lines, produces
    --
    with connected_lines as (
    select row_number() over (order by 1) as rid,
           f.geom
      from (select sdo_geometry(2002,8292,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(sx,sy,ex,ey)) as geom
              from (select distinct sx,sy,ex,ey,dist,
                           min(dist) over (partition by sx,sy) as mdist
                      from (select a.x as sx,a.y as sy,b.x as ex,b.y as ey,
                                   sdo_geom.sdo_distance(sdo_geometry(2001,8292,sdo_point_type(a.x,a.y,null),null,null),
                                                         sdo_geometry(2001,8292,sdo_point_type(b.x,b.y,null),null,null),
                                                         0.005) as dist
                              from (select p.x as x, p.y as y
                                      from outerLines g,
                                           table(geom.getVector(g.geom)) v,
                                           table(geom.getPointSet(v.AsSdoGeometry(8292))) p
                                    group by p.x, p.y
                                    having count(*) = 1
                                   ) a,
                                   (select p.x as x, p.y as y
                                      from outerLines g,
                                           table(geom.getVector(g.geom)) v,
                                           table(geom.getPointSet(v.AsSdoGeometry(8292))) p
                                    group by p.x, p.y
                                    having count(*) = 1
                                   ) b
                              where a.x != b.x and a.y != b.y
                            )
                    )
                    where dist = mdist
            UNION ALL
            select g.geom
              from outerLines g
          ) f
    )
    /* Now ask SC4O's ST_PolygonBuilder to try and create a polygon from the set of lines */
    select sc4o.ST_PolygonBuilder(CAST(COLLECT(f.geom) as mdsys.sdo_geometry_array),8) as polygon
      from ( /* Now, the WITH connected_lines produces 2 copies of each linestring with the coordinates reversed.
                    These have to be removed/de-duped before being passed into the ST_PolygonBuilder */
            select sdo_geometry(2002,8292,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(sum(x1),sum(y1),sum(x2),sum(y2))) as geom
              from (SELECT rid,
                           case when rid=NVL((lag(rid,1) over (partition by rid order by x)),rid)
                                then case when vertexId = 1 then x else null end
                            end as x1,
                           case when rid=NVL((lag(rid,1) over (partition by rid order by x)),rid)
                                then case when vertexId = 1 then y else null end
                            end as y1,
                           case when rid=NVL((lag(rid,1) over (partition by rid order by x)),rid)
                                then case when vertexId = 2 then x else null end
                            end as x2,
                           case when rid=NVL((lag(rid,1) over (partition by rid order by x)),rid)
                                then case when vertexId = 2 then y else null end
                            end as y2
                    FROM   (select rid,
                                   row_number() over (partition by rid order by x) as vertexId,
                                   x, y
                              from (select min(m.rid) rid,
                                           t.x, t.y
                                      from connected_lines m,
                                           table(sdo_util.getVertices(m.geom)) t
                                     where sdo_util.GetNumVertices(m.geom) = 2
                                     group by t.x,t.y
                                     order by t.x )
                           )
                      )
                    group by rid
        union all
        /* Select and pass into ST_PolygonBuilder the original outer lines */
        select m.geom as geom
          from connected_lines m
         where sdo_util.GetNumVertices(m.geom) > 2
        ) f;
    -- Result
    --
    POLYGON
    -----------------------
    MDSYS.SDO_GEOMETRY(2003,8292,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1),MDSYS.SDO_ORDINATE_ARRAY(-49.6906307026931,-18.4950115281619,-49.6886251490431,-18.4958803030445,-49.6882811644211,-18.4960292763006,-49.6875224063873,-18.4994400734344,-49.6878936628642,-18.4995538840232,-49.6878678853177,-18.4996181336176,-49.6861731626715,-18.4991017919552,-49.6834080082784,-18.4982775371379,-49.6833583465082,-18.4983066497055,-49.6832975737928,-18.4983520405102,-49.6831594052426,-18.4984987309426,-49.6830586383606,-18.4986094463067,-49.6829994956301,-18.4986769870823,-49.6829194669485,-18.4987385992949,-49.6828337343539,-18.4987905933782,-49.6827167582476,-18.4988411048671,-49.6825978712605,-18.4988566328165,-49.6824876108137,-18.4988587567866,-49.6824343436196,-18.4988638980162,-49.6823495710101,-18.498901802054,-49.6820036074112,-18.4990727977958,-49.6815739264209,-18.4993045655044,-49.6815394467332,-18.4993194542279,-49.6815037571481,-18.4993313944568,-49.681467095582,-18.4993402576461,-49.6814297528519,-18.4993459734892,-49.6813920251781,-18.4993484966453,-49.6813542118344,-18.4993478070996,-49.6813166127745,-18.4993439103221,-49.6812795262518,-18.4993368372241,-49.6812432464542,-18.4993266439127,-49.6812080820875,-18.4993134018902,-49.6793284309429,-18.5001537628556,-49.6792385551751,-18.5000418095053,-49.6797119992317,-18.4998345697814,-49.6783397446724,-18.4980535328215,-49.6810365599698,-18.4971609552001,-49.6810385833744,-18.4971564511947,-49.6835051531636,-18.4963355157698,-49.6833312619652,-18.4958030666281,-49.6834396716227,-18.4957578264012,-49.6836133980005,-18.4962994912622,-49.6860079716291,-18.4955025995491,-49.6857982402423,-18.4950861997106,-49.6855427926656,-18.4945793006294,-49.6849860033691,-18.4934740072225,-49.6885491287687,-18.4923048595269,-49.6883413960309,-18.4918992292229,-49.6884083531774,-18.4917625230274,-49.6886528151554,-18.4922451253898,-49.6898503241639,-18.4946091658756,-49.690098431643,-18.4950991112698,-49.6902068702432,-18.4950498009285,-49.6905958643821,-18.4948724904445,-49.6906307026931,-18.4950115281619))
    

    The result is a nice clean polygon.

    http://www.spatialdbadvisor.com/files/PolygonCoveringGeometrySet.PNG

    This, more than my last post is the best I can do. It took me many, many hours to implement. Please allow points since it is a correct result. Also, consider making a PayPal donation on my Web site for the hours I spent.

    NOTE: The package space companion 4 Oracle (SC4O) is available for download FREE on my site. Again, donations accepted if the code made what you want.

    concerning
    Simon

    Published by: Simon Greener on April 11, 2013 09:53 Changed where a.x, b.x and b.y-a.y etc. to where a.x! = b.x and a.y! b.y =

  • How to find the nearest point to polyline

    Hello

    I find the point closest to my point of view standing on a polyline. I have Oracle Locator installed, but my data is not in a format locator. Is it possible to do using the functionality of the telecommunications service provider with, for example, the polyline and permanent values of coordinates of points in a space variable by calling some localization features?

    Or I must coordinate data in a spatial 'permit' table, create the spatial index, etc. and then call a procedure Locator.

    Tamas

    Luke,

    Thanks for the reference.

    When the data is converted, the Summit nearest to find an object of sdo_geometry could be done this way (of, of course, for the most part):

    select f.vertex_id,f.dist,f.min_dist,f.a_vertex
      from (select p.vertex_id,
                   sdo_geom.sdo_distance(p.the_point,p.a_vertex,0.005) as dist,
                   min(sdo_geom.sdo_distance(p.the_point,p.a_vertex,0.005)) over (order by sdo_geom.sdo_distance(p.the_point,p.a_vertex,0.005) asc) as min_dist,
                   p.the_point,
                   p.a_vertex
              from (select t.id as vertex_id,
                           mdsys.sdo_geometry(2001,NULL,mdsys.sdo_point_type(358615,5407047,null),null,null) as the_point,
                           mdsys.sdo_geometry(2001,NULL,mdsys.sdo_point_type(t.x,t.y,t.z),null,null) as a_vertex
                      from table(sdo_util.getVertices(
                                MDSYS.SDO_GEOMETRY(2002,null,null,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(362253.9,5409676.63,355608.12,5407615.16,358063.37,5407673.48,355276.53,5407361.08,360471.08,5408880.79,362483.4,5406024.69,362359.16,5408840.11,354570.21,5406219.18,360204.62,5405849.14,359214.51,5408283.5,358761.06,5406683.88,356739.05,5405590.46,358615.79,5407047.29,355978.02,5407326.33,356240.87,5409898.7,363159.35,5405510.46,358588.81,5406536.54,354822.42,5408643.75,357690.2,5408872.57,359839.29,5407253.86,355236.29,5409711.53,355342.54,5407448.87,360290.53,5405111.51,354677.02,5407916.83,361651.27,5409178.26,361730.18,5407553.5,357402.33,5409065.5,361546.51,5407278.41,361915.65,5408942.57,361974.74,5405464.91,357794.3,5406979.33,356106.58,5405481.32,357604.96,5407407.72,360718.31,5406765.8,359745.49,5406568.16,363005.29,5407557.46,355844.01,5407095.47,362749.66,5405041.82,359714.13,5408898.69,354509.69,5406113.6,360041.59,5406204.24,360380.17,5408751.21,356621.4,5409603.06,355156.27,5405401.98,354441.35,5409090.68,356376.45,5407472.81,363877.1,5405582.72,361883.83,5409696.17,356363.41,5406434.53,362078.96,5406617.37,362714.59,5409800.2,362703.49,5408513.33,358317.64,5408170.64,359294.27,5409197.53,360240.93,5406333.84))
                                )) t
                    ) p
            ) f
      where f.dist = f.min_dist;
    

    I hope this helps.

    Simon

  • WITH the ORDER BY clause and bug SDO_GEOMETRY?

    I'm having a problem using SDO_GEOMETRY in a WITH clause. Specifically with ORDER BY. I'll show a shortened version of SQL here. I'm doing something wrong or is this a bug?

    It works:
                         SELECT 
            loc.location_id,
                        SDO_GEOM.SDO_DISTANCE(cent.lat_long, 
                        MDSYS.SDO_GEOMETRY
                        (
                        2001, -- SDO_GTYPE attribute: 2 in 2001 specifies dimensionality is 2.
                        '4326', 
                        SDO_POINT_TYPE(-78.6386145, 35.772096, NULL),
                        NULL,
                        NULL
                        ),
                       0.01, -- tolerance
                        'unit=mile') result_center_distance
                        
              
                         FROM location loc
                         JOIN centroid cent ON loc.centroid_id = cent.centroid_id
             ORDER BY result_center_distance
    After the statement select in a with clause, this does not work, which gives an identifier not valid "SDO_GEOMETRY" ORA-00904:
    WITH location_distance AS
    (
                         SELECT 
            loc.location_id,
                        SDO_GEOM.SDO_DISTANCE(cent.lat_long, 
                        MDSYS.SDO_GEOMETRY
                        (
                        2001, -- SDO_GTYPE attribute: 2 in 2001 specifies dimensionality is 2.
                        '4326', 
                        SDO_POINT_TYPE(-78.6386145, 35.772096, NULL),
                        NULL,
                        NULL
                        ),
                       0.01, -- tolerance
                        'unit=mile') result_center_distance                    
              
                         FROM location loc
                         JOIN centroid cent ON loc.centroid_id = cent.centroid_id
             ORDER BY result_center_distance
      ) SELECT * from location_distance
    If I duplicate the function of the distance in the ORDER BY, it works:
    WITH location_distance AS
    (
                         SELECT 
            loc.location_id,
                        SDO_GEOM.SDO_DISTANCE(cent.lat_long, 
                        MDSYS.SDO_GEOMETRY
                        (
                        2001, -- SDO_GTYPE attribute: 2 in 2001 specifies dimensionality is 2.
                        '4326', 
                        SDO_POINT_TYPE(-78.6386145, 35.772096, NULL),
                        NULL,
                        NULL
                        ),
                       0.01, -- tolerance
                        'unit=mile') result_center_distance                    
              
                         FROM location loc
                         JOIN centroid cent ON loc.centroid_id = cent.centroid_id
             ORDER BY                     SDO_GEOM.SDO_DISTANCE(cent.lat_long, 
                MDSYS.SDO_GEOMETRY
                (
                2001, -- SDO_GTYPE attribute: 2 in 2001 specifies dimensionality is 2.
                '4326', 
                SDO_POINT_TYPE(-78.6386145, 35.772096, NULL),
                NULL,
                NULL
                ),
                  0.01, -- tolerance
                'unit=mile')
      ) SELECT * from location_distance

    This is a bug. But it is set to 11g R2. Note that this is not a space bug, but a bug in generic compilation.

  • Calculation of the distance of the location GPS provider

    I'm looking to develop an application of GPS based location by saving a LocationListener with the LocationProvider, I need to be able to calculate the distance between two cooridinates.

    The Coordinates () .distance method doesn't seem to work, also responds to 0.

    I saw and distance example where speed and range were used to calculate, but I was wondering is this reliable?

    An alternative is to calculate the distance between two coordinates using the Haversine formula, the java class Math in Blackberry JDE however does not have the required operation atan2. Anyone know of any alternative?

    Thank you

    Dave

    In my experience, the distance calculation works.  What results are you seeing?  Are you sure these two places are valid?

    I would not use speed and interval unless there is no other choice, or that the interval was small.

    The quesiton on atan was invited to this forum, have a search for her.  Here is an answer:

    BB has no ACON, ATAN, ASIN

    http://supportforums.BlackBerry.com/Rim/Board/message?board.ID=java_dev&message.ID=142&query.ID=2195...

  • shortest distance

    Hi, I have a table of geometry of point, to select the intermediate points which gives the shortest between two predefined points (point 1 and point 2) using sdo_geom.sdo_distance.

    ID X Y
    point 1: 6143 - 87.910994 41.982889
    point 2: 6048 - 87.907813 41.982816

    intermediate points:

    point 3: 5991 - 87.909845 41.9828835
    point 4: 5994 - 87.908649 41.98287
    point 5: 5993 - 87.908798 41.9826835
    point 6: 6033 - 87.908493 41.9825935

    any suggestions?
    Thank you

    If you want to find 3 points, you must use 3 loops FOR and concat 3 indexes for the ROAD:

    SET SERVEROUTPUT ON SIZE 900000;
    
    DECLARE
      TYPE points IS TABLE OF sdo_geometry;
    
      ipoints points :=  points();
      apoint sdo_geometry := sdo_geometry(2001, 8307, sdo_point_type(-87.910994, 41.982889 , 0), NULL , NULL);
      epoint sdo_geometry := sdo_geometry(2001, 8307, sdo_point_type(-87.907813, 41.982816 , 0), NULL, NULL);   
    
      dist   NUMBER := 0;
      sumd   NUMBER := 9999999;
    
      route  VARCHAR2(200) := '';
    
    BEGIN
    
      --initialize
      ipoints.extend(3);
      ipoints(1) := sdo_geometry(2001, 8307,sdo_point_type( -87.905464, 41.967392, 0), NULL, NULL);
      ipoints(2) := sdo_geometry(2001, 8307,sdo_point_type( -87.904189, 41.967377, 0), NULL, NULL);
      ipoints(3) := sdo_geometry(2001, 8307,sdo_point_type( -87.901859, 41.9673795,0), NULL, NULL);
    
      --brute force
      FOR i IN 1..3 LOOP
        FOR j IN 1..3 LOOP
          FOR k IN 1..3 LOOP
              --dont use same point twice !
              IF (i=j OR i=k OR j=k) THEN CONTINUE;END IF;
              dist  := sdo_geom.sdo_distance(apoint    ,ipoints(i),1) +
                       sdo_geom.sdo_distance(ipoints(i),ipoints(j),1) +
                       sdo_geom.sdo_distance(ipoints(j),    epoint,1);
              --get the actual route
              IF sumd>dist THEN
                sumd  := dist;
                route := to_char(i)||to_char(j)||to_char(k);
              END IF;
          END LOOP;
        END LOOP;
      END LOOP;
    
      --length of shortest path
      dbms_output.put_line ('route='||route);
      dbms_output.put_line (sumd);
    END;
    
    route=123
    3627,935355905372
    

    The brute force method (in this very simple case) needs more iterations for each intermediate point (n * n), so it cannot be used for a large number of points.
    In this thread there are links and advice for other methods in these cases.

    POINTS ITERATIONS
    ----------------------------
    1            1
    2            4
    3           27
    4          265
    5         3125
    6        46656
    ...
    10 10000000000
    

    BTW. You should use markup bat, to format your code and the intention of the lines, you see the difference, not you?

Maybe you are looking for

  • PanoStandAlone

    What is "PanoStandAlone"?  Where did this come from?  Why can't find it so I can REMOVE it?

  • Como detectar el lugar keeps me UN got mail

    OK me mando invitasion segun muy ermosa por sus fotos mujer y the pajina that the desia than estaba en esporeso a siudad as eya pero yo misma me dijo than estaba Africa y despues me comenso a pedir dinero y eso fue lo me causo desconfiansa porque nor

  • What is events from COM + has stopped working?

    How can I solve this problem?

  • Pavilion DV7 3150ed installation of the wireless driver

    Due to problem that I have reinstalled Windows7 on my Pavilion DV7 3150ed but now I not see wlan installed, I see only Bluetooth. The pictograms said WLAN and Bluetooth are disabled. How can I anable both? Is it a driver problem?

  • Cleaning LTO5 TL4000 tape

    Hello We have a TL4000 with LTO5 readers. I need a cleaning tape and will not be able to wait until Dell can ship us. I've been watching a few bands available on another site which I will be able to get Monday and I was wondering if I need to find a