Top 5 Recent Articles
ARTICLES CATEGORIES
- Algorithms (22)
- All (399)
- Biography (1)
- Blog (44)
- Business Requirements (1)
- Commentary (1)
- Conversion (2)
- Customers (2)
- Data Models (1)
- Education (2)
- GeoRaptor (13)
- GPS (1)
- Image Processing (2)
- Import Export (8)
- Licensing (2)
- LiDAR (1)
- Linear Referencing (4)
- Manifold GIS (3)
- Mapping (1)
- MySQL Spatial (7)
- Networking and Routing (including Optimization) (5)
- Open Source (18)
- Oracle Spatial and Locator (194)
- Partitioning (1)
- PostGIS (36)
- Projections (1)
- Published Articles (1)
- qGIS (1)
- Recommendations (1)
- Services (1)
- Software Change Log (1)
- Source Code (37)
- Space Curves (9)
- Spatial Database Functions (109)
- Spatial DB comparison (1)
- Spatial XML Processing (11)
- SQL Server Spatial (92)
- Standards (3)
- Stored Procedure (17)
- Tessellation or Gridding (10)
- Tools (2)
- Topological Relationships (1)
- Training (2)
- Triangulation (2)
How far inside, is inside? Measuring actual distance.
One issue that confuses a lot of spatial database practitioners is that the result of measuring the distance between a geometry object inside a polygon and that polygon’s boundary is zero (0).
Here is an example.
SELECT sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(0,0,100,100)) AS outerPoly, sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(10,10,90,90)) AS innerPoly FROM dual;
This looks like:
Standard distance determination shows the problem:
SELECT sdo_geom.sdo_distance( sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(0,0,100,100)), sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(10,10,90,90)), 0.005) AS dist FROM dual; -- -- Results -- DIST ---------- 0
Here is a trick that will allow for the calculation of a distance between the inner polygon and the one that contains it. Firstly, turn the outer polygon into a linestring, and then calculate the distance.
SELECT sdo_geom.sdo_distance( sdo_util.polygonToLine(sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(0,0,100,100))), sdo_geometry(2003,NULL,NULL,sdo_elem_info_array(1,1003,3),sdo_ordinate_array(10,10,90,90)), 0.005) AS dist FROM dual; -- -- Results -- DIST ---------- 10
The zero (0) distance problem also affects SDO_NN and other distance operators. The same trick can be used with those operators or functions.
UPDATE
In response to a comment in respect of whether this trick works for non-rectangular polygons, the answer is yes.
WITH tGeom AS ( SELECT SDO_GEOMETRY(2003,3112,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1,65,2003,1),SDO_ORDINATE_ARRAY( 1030522.796,-1739721.758, 1038890.414,-1751951.354, 1134796.194,-1713331.577, 1174059.635,-1723630.184, 1055625.651,-1777697.872, 1100682.058,-1776410.546, 1165692.016,-1772548.569, 1214610.401,-1766755.602, 1245506.222,-1723630.184, 1246793.548,-1699814.655, 1236494.941,-1664413.192, 1195944.175,-1647034.292, 1172772.309,-1657332.9, 1158611.724,-1672780.811, 1137370.846,-1694665.351, 1119348.283,-1698527.329, 1098751.069,-1694665.351, 1091670.776,-1684366.744, 1091670.776,-1673424.474, 1094889.091,-1661838.54, 1091670.776,-1642528.652, 1079441.18,-1629655.393, 1052407.336,-1634161.033, 1029235.47,-1643172.315, 1019580.525,-1648965.281, 1015718.548,-1659907.552, 1020224.188,-1679861.103, 1045327.044,-1690803.373, 1071073.562,-1699170.992, 1082659.495,-1723630.184, 1057556.64,-1731354.139, 1030522.796,-1739721.758, /* hole */ 1040177.74,-1658620.226, 1068498.91,-1647034.292, 1070429.899,-1667631.507, 1053694.662,-1674711.799,1057556.64,-1661194.877, 1040177.74,-1658620.226)) AS geom FROM dual ), tPoints AS ( SELECT p.column_value AS pointId, sdo_util.EXTRACT(SDO_GEOMETRY(2005,3112,NULL,SDO_ELEM_INFO_ARRAY(1,1,11),SDO_ORDINATE_ARRAY( 1065924.258,-1656689.237, 1040821.403,-1744227.399, 1215254.064,-1711400.588, 1181139.927,-1663769.529, 1251942.852,-1786709.154, 1259666.807,-1638666.674, 998339.648,-1701745.644, 1134796.194,-1641241.326, 1129646.891,-1726848.499, 1119348.283,-1786065.491, 1075579.203,-1754526.006)),1,p.column_value) AS point FROM TABLE(codesys.geom.generate_series(1,11,1)) p ) SELECT b.pointid, round(sdo_geom.sdo_distance(a.geom,b.point,0.005),2) AS distPoly, round(sdo_geom.sdo_distance(sdo_util.polygonToLine(a.geom),b.point,0.005),2) AS distLine FROM tGeom a, tpoints b; -- Result -- POINTID DISTPOLY DISTLINE ------- -------- --------- 1 3464.61 3464.61 2 0 5955.25 3 0 30868.15 4 0 9280.28 5 41968.69 41968.69 6 34638.40 34638.40 7 30949.41 30949.41 8 38867.72 38867.72 9 10615.05 10615.05 10 10744.89 10744.89 11 12792.61 12792.61 -- 11 ROWS selected
Rendering points by pointid, poly and line distance “(id) distPoly / distLine” looks like this:
I hope this is of use to someone out there.
Documentation
- MySQL Spatial General Functions
- Oracle LRS Objects
- Oracle Spatial Exporter (Java + pl/SQL)
- Oracle Spatial Object Functions
- Oracle Spatial Object Functions (Multi Page)
- PostGIS pl/pgSQL Functions
- SC4O Oracle Java Topology Suite (Java + pl/SQL)
- SQL Server Spatial General TSQL Functions
- SQL Server Spatial LRS TSQL Functions