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)
Convert Single Point stored in SDO_ORDINATES to SDO_POINT_TYPE
Oracle Spatial offers two ways of storing a single point:
- In SDO_POINT_TYPE structure
- In SDO_ORDINATE_ARRAY
Examples include:
- SDO_GEOMETRY(2001,NULL,SDO_POINT_TYPE(12, 14, NULL),NULL,NULL))
- SDO_GEOMETRY(2001,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1,1),SDO_ORDINATE_ARRAY(12,14))
Oracle recommends the storage of single points using the SDO_POINT_TYPE structure. There are, of course, a number of situations where this is not possible or recommended:
- Storage using the SDO_POINT_TYPE structure is impossible if the point had more than 3 ordinates.
- If the geometry type of a particular SDO_GEOMETRY column in a table is MULTIPOINT and a particular observed value is a single point, multipoint.
How is it that SDO_ORDINATE_ARRAY based single points arise? Variously. The most common is that external loading software does so using a wrong parameter (some loader have switches for loading into SDO_POINT_TYPE rather than SDO_ORDINATE_ARRAY but the user forgets to set the right switch). Others (I’m guessing here) include ignorance; perhaps perceptions that a homogeneous approach to storing all geometry ordinates using the one method somehow brings benefits in terms of programming, support etc.
Conversion from SDO_ORDINATE_ARRAY to SDO_POINT_TYPE can occur in two ways:
- Straight SQL
- PL/SQL function.
Straight SQL
This is an easy thing to do as the following shows.
WITH cTable AS ( SELECT SDO_GEOMETRY(2001,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1,1),SDO_ORDINATE_ARRAY(12,14)) AS oGeom FROM DUAL ) SELECT SDO_GEOMETRY(2001,a.oGeom.sdo_srid,SDO_POINT_TYPE(t.x,t.y,NULL),NULL,NULL) AS point FROM cTable a, TABLE(Sdo_Util.GetVertices(a.oGeom)) t WHERE t.id = 1; -- Results -- POINT ------------------------------------------------------------ SDO_GEOMETRY(2001,NULL,SDO_POINT_TYPE(12,14,NULL),NULL,NULL)
Now if we had more than one point in the sdo_ordinate_array we can process them all by dropping off the t.id = 1 predicate as follows:
WITH cTable AS ( SELECT SDO_GEOMETRY(2001,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1,3),SDO_ORDINATE_ARRAY(12,14,120,140,1200,1400)) AS oGeom FROM DUAL ) SELECT SDO_GEOMETRY(2001,a.oGeom.sdo_srid,SDO_POINT_TYPE(t.x,t.y,NULL),NULL,NULL) AS point FROM cTable a, TABLE(Sdo_Util.GetVertices(a.oGeom)) t; -- Results -- POINT ---------------------------------------------------------------------- SDO_GEOMETRY(2001,NULL,MDSYS.SDO_POINT_TYPE(12,14,NULL),NULL,NULL) SDO_GEOMETRY(2001,NULL,MDSYS.SDO_POINT_TYPE(120,140,NULL),NULL,NULL) SDO_GEOMETRY(2001,NULL,MDSYS.SDO_POINT_TYPE(1200,1400,NULL),NULL,NULL)
Now let’s look at the PL/SQL approach.
PL/SQL function.
There is a function in my PL/SQL GEOM package called ToSdoPoint that is as follows:
FUNCTION ToSdoPoint( p_geometry IN MDSYS.SDO_GEOMETRY ) RETURN MDSYS.SDO_GEOMETRY IS v_element NUMBER; v_elements NUMBER; v_geometry MDSYS.SDO_Geometry; v_SdoPoint MDSYS.SDO_Point_Type := MDSYS.SDO_Point_Type(0,0,NULL); v_Ordinates MDSYS.SDO_Ordinate_Array; BEGIN IF ( MOD(p_geometry.sdo_gtype,10) NOT IN (1,5) ) THEN v_geometry := NULL; ELSIF p_geometry.sdo_point IS NOT NULL THEN v_geometry := mdsys.sdo_geometry(p_geometry.sdo_gtype,p_geometry.sdo_srid,p_geometry.sdo_point,NULL,NULL); ELSE v_ordinates := p_geometry.sdo_ordinates; v_SdoPoint.X := v_ordinates(1); v_SdoPoint.Y := v_ordinates(2); IF ( FLOOR(p_geometry.sdo_gtype/1000) = 3 ) THEN v_SdoPoint.Z := v_ordinates(3); END IF; v_geometry := mdsys.sdo_geometry(p_geometry.sdo_gtype,p_geometry.sdo_srid,v_SdoPoint,NULL,NULL); END IF; RETURN v_geometry; END ToSdoPoint;
This can be used as follows.
WITH cTable AS ( SELECT SDO_GEOMETRY(2001,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1,1),SDO_ORDINATE_ARRAY(12,14)) AS oGeom FROM DUAL ) SELECT GEOM.ToSdoPoint(a.oGeom) AS point FROM cTable a; -- Results -- POINT ------------------------------------------------------------ SDO_GEOMETRY(2001,NULL,SDO_POINT_TYPE(12,14,NULL),NULL,NULL)
I hope this is of use to someone.
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