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)
Line Merging or Collecting lines together: ST_LineMerger
One activity that is very common when working with linear data is to be able to take a bunch of linestrings and collect them together into a minimal set of maximum length linestrings.
The Java Topology Suite (JTS) has a LineMerger class that does this very nicely.
I have integrated this into my Spatial Companion For Oracle (SC4O) project.
/** * ST_LineMerger * Takes set of linestring geometries and constructs a collection of linear components * that form maximal-length linestrings. The linear components are returned as a MultiLineString. * @param p_resultSet : RefCur_T : Ref Cursor of Linestring Geometries * @param p_precision : int : Number of decimal places of precision when comparing ordinates. * @return STRUCT : Collection of linear sdo_geometries as MultiLineString. * @throws SQLException * @history Simon Greener, January 2012, Original Coding * @copyright : Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. * http://creativecommons.org/licenses/by-sa/2.5/au/ */ FUNCTION ST_LineMerger(p_resultSet IN &&defaultSchema..SC4O.refcur_t, p_precision IN NUMBER) RETURN mdsys.sdo_geometry Deterministic; . /** * ST_LineMerger * Takes set of linestring geometries and constructs a collection of linear components * that form maximal-length linestrings. The linear components are returned as a MultiLineString. * @param p_resultSet : T_GeometrySet : Table of Linestring Geometries * @param p_precision : int : Number of decimal places of precision when comparing ordinates. * @return STRUCT : Collection of linear sdo_geometries as MultiLineString. * @throws SQLException * @history Simon Greener, January 2012, Original Coding * @copyright : Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. * http://creativecommons.org/licenses/by-sa/2.5/au/ */ FUNCTION ST_LineMerger(p_geomset IN &&defaultSchema..t_geometrySet, p_precision IN NUMBER) RETURN mdsys.sdo_geometry Deterministic;
Here is an example.
-- Show the lines -- WITH LINES AS ( SELECT sdo_geometry('LINESTRING (220 160, 240 150, 270 150, 290 170)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (60 210, 30 190, 30 160)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 430, 100 430, 120 420, 140 400)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 160 280, 160 250, 170 230)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (170 230, 180 210, 200 180, 220 160)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (30 160, 40 150, 70 150)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 200 330, 220 340, 240 360)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (140 400, 150 370, 160 340, 160 310)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 130 300, 100 290, 70 270)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (240 360, 260 390, 260 410, 250 430)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 150, 100 180, 100 200)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 270, 60 260, 50 240, 50 220, 60 210)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (100 200, 90 210, 60 210)',NULL) AS geom FROM dual ) SELECT rownum AS id, geom FROM LINES; -- Rsults ID GEOM -- -------------------------------------------------------------------------------------------------------------------------------- 1 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(220,160,240,150,270,150,290,170)) 2 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(60,210,30,190,30,160)) 3 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(70,430,100,430,120,420,140,400)) 4 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,160,280,160,250,170,230)) 5 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(170,230,180,210,200,180,220,160)) 6 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(30,160,40,150,70,150)) 7 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,200,330,220,340,240,360)) 8 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(140,400,150,370,160,340,160,310)) 9 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,130,300,100,290,70,270)) 10 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(240,360,260,390,260,410,250,430)) 11 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(70,150,100,180,100,200)) 12 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(70,270,60,260,50,240,50,220,60,210)) 13 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(100,200,90,210,60,210)) . 13 ROWS selected
This looks like this….
-- Now do the Line Merging. -- WITH stuff AS ( SELECT CAST( multiset( SELECT sdo_geometry('LINESTRING (220 160, 240 150, 270 150, 290 170)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (60 210, 30 190, 30 160)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 430, 100 430, 120 420, 140 400)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 160 280, 160 250, 170 230)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (170 230, 180 210, 200 180, 220 160)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (30 160, 40 150, 70 150)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 200 330, 220 340, 240 360)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (140 400, 150 370, 160 340, 160 310)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (160 310, 130 300, 100 290, 70 270)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (240 360, 260 390, 260 410, 250 430)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 150, 100 180, 100 200)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (70 270, 60 260, 50 240, 50 220, 60 210)',NULL) AS geom FROM dual UNION ALL SELECT sdo_geometry('LINESTRING (100 200, 90 210, 60 210)',NULL) AS geom FROM dual ) AS t_geometrySet) AS mLine FROM dual ) SELECT rownum AS Id, t.* FROM stuff s, TABLE(geom.ExplodeGeometry(geom.ExtractLine(SC4O.st_linemerger(s.mline,3)))) t; -- Results ID GEOMETRY -- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(60,210,30,190,30,160,40,150,70,150,100,180,100,200,90,210,60,210)) 2 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,130,300,100,290,70,270,60,260,50,240,50,220,60,210)) 3 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(70,430,100,430,120,420,140,400,150,370,160,340,160,310)) 4 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,200,330,220,340,240,360,260,390,260,410,250,430)) 5 MDSYS.SDO_GEOMETRY(2002,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),MDSYS.SDO_ORDINATE_ARRAY(160,310,160,280,160,250,170,230,180,210,200,180,220,160,240,150,270,150,290,170))
This looks like this….
I hope this is useful 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