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)
Create Polygons and Linestrings From Bearings And Distances (COGO)
UPDATE
The original functions have been modified and deployed via my Oracle Object code.
They original code is no longer available.
My COordinate GeOmetry (COGO) package has been around for a long time.
What I had not done was use the power of this package to construct polygons (2003) or linestrings (2002) from a starting point and a set of whole circle bearings (0-360) and distances.
The following article shows how some simple COGO functionality has been added to my Oracle Object type system.
Representing Bearings and Distances
Firstly a data type to represent bearing and distances instructions is created, and some useful Constructors are added to allow for different methods for defining bearings.
-- Create a suitable type for the bearings and distances -- CREATE OR REPLACE TYPE T_Bearing_Distance AUTHID DEFINER AS OBJECT ( Bearing NUMBER, Distance NUMBER, Z NUMBER, Constructor FUNCTION T_BEARING_DISTANCE ( p_sDegMinSec IN varchar2, p_distance IN NUMBER ) RETURN SELF AS RESULT, Constructor FUNCTION T_BEARING_DISTANCE ( p_bearing IN NUMBER, p_distance IN NUMBER ) RETURN SELF AS RESULT, Constructor FUNCTION T_BEARING_DISTANCE ( p_sDegMinSec IN varchar2, p_distance IN NUMBER, p_z IN NUMBER ) RETURN SELF AS RESULT ); / SHOW ERRORS . -- We need a collection of bearings and distances to create a polygon -- CREATE TYPE tbl_bearing_distances AS TABLE OF T_Bearing_Distance; / SHOW errors
Now we can add three member functions to T_Geometry type.
- ST_Cogo2Line – Creates single linestring from supplied bearing and distance instructions.
- ST_Line2Cogo – Creates Cogo Instructions from linestring segments.
- ST_Cogo2Polygon – Creates single polygon exterior ring from supplied bearing and distance instructions.
(ST_Polygon2Cogo is yet to be built as I have to add the ability to “Move To” in the bearings and distances to handle polygons with many rings.)
ST_Cogo2Line
This function starts with a point (T_GEOMETRY) object, and constructs a single linestring object from the passed in set of bearings and distances. (A dedicated Constructor will be added at some stage to enable objects to be created from scratch.
CREATE OR REPLACE TYPE T_GEOMETRY AS ... . -- Create a function that operates on a T_GEOMETRY Point and a set of bearings and distances to create a linestring Member FUNCTION ST_Cogo2Line(p_bearings_and_distances IN T_BEARING_DISTANCES) RETURN T_Geometry Deterministic, . -- Examples -- Build 2D Line from default constructor SELECT F.line.ST_Validate() AS vLine, f.line.geom AS line, round(f.line.ST_Length(),2) AS meters FROM (SELECT t_geometry(sdo_geometry(2001,NULL,sdo_point_type(0.0,3.5,NULL),NULL,NULL),0.005,2,1) .ST_Cogo2Line ( t_bearing_distances( t_bearing_distance(180.00,3.50,NULL), t_bearing_distance( 90.00,3.50,NULL), t_bearing_distance( 0.00,3.50,NULL), t_bearing_distance( 43.02,5.43,NULL), t_bearing_distance(270.00,9.50,NULL) ) ) .ST_Round(8,8) AS line FROM dual ) f; . VLINE LINE METERS ----- ----------------------------------------------------------------------------------------------------------------------------------------------------------- ------ TRUE SDO_GEOMETRY(2002,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,2,1),SDO_ORDINATE_ARRAY(0.0,3.5, 0.0,0.0, 3.5,0.0, 3.5,3.5, 7.2046371,7.46995768, -2.2953629,7.46995768)) 25.43 . -- Build 3D line by decimal degrees using default constructor SELECT F.line.ST_Validate() AS vLine, f.line.geom AS line, round(f.line.ST_Length(),2) AS meters FROM (SELECT T_Geometry(sdo_geometry(3001,NULL,sdo_point_type(0,3.5,0),NULL,NULL),0.005,2,1) .ST_Cogo2Line( p_bearings_and_distances=> t_bearing_distances( t_bearing_distance(180, 3.5, 0.1), t_bearing_distance(90, 3.5, 0.5), t_bearing_distance(0, 3.5, 1.6), t_bearing_distance(43.02,5.43,2.123), t_bearing_distance(270, 9.5, 0.5) ) ) .ST_Round(8,8) AS line FROM dual ) f; . VLINE LINE METERS ----- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------ TRUE SDO_GEOMETRY(3002,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,2,1),SDO_ORDINATE_ARRAY(0.0,3.5,0.0, 0.0,0.0,0.1, 3.5,0.0,0.5, 3.5,3.5,1.6, 7.2046371,7.46995768,2.123, -2.2953629,7.46995768,0.5)) 25.79 . -- Line by degrees using text constructor SELECT F.line.ST_Validate() AS vLine, f.line.geom AS line, round(f.line.ST_Length(),2) AS meters FROM (SELECT T_Geometry(sdo_geometry(3001,NULL,sdo_point_type(0,3.5,0),NULL,NULL),0.005,2,1) .ST_Cogo2Line( p_bearings_and_distances=> t_bearing_distances( t_bearing_distance(p_sDegMinSec=>'180', p_distance=>3.5, p_z=>0.1), t_bearing_distance(p_sDegMinSec=>'90', p_distance=>3.5, p_z=>0.5), t_bearing_distance(p_sDegMinSec=>'0', p_distance=>3.5, p_z=>1.6), t_bearing_distance(p_sDegMinSec=>'43^01''21"', p_distance=>5.43, p_z=>2.0), t_bearing_distance(p_sDegMinSec=>'270', p_distance=>9.5, p_z=>0.5), t_bearing_distance(p_sDegMinSec=>'149^58''6.3"',p_distance=>4.613,p_z=>0.1)) ) .ST_Round(8,8) AS line FROM dual ) f; . VLINE LINE METERS ----- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------ TRUE SDO_GEOMETRY(3002,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,2,1),SDO_ORDINATE_ARRAY(0.0,3.5,0.0, 0.0,0.0,0.1, 3.5,0.0,0.5, 3.5,3.5,1.6, 7.20481032,7.46979603,2.0, -2.29518968,7.46979603,0.5, 0.01351213,3.47609287,0.1)) 30.39 . -- Build 3D line using mixed constructors SELECT F.line.ST_Validate() AS vLine, f.line.geom AS line, round(f.line.ST_Length(),2) AS Meters FROM (SELECT T_Geometry(sdo_geometry(3001,NULL,sdo_point_type(0,3.5,0),NULL,NULL),0.005,2,1) .ST_Cogo2Line( p_bearings_and_distances=> t_bearing_distances( t_bearing_distance( 180.0, 3.5, 0.1), -- << Default Constructor t_bearing_distance(p_sDegMinSec=>'90', p_distance=>3.5, p_z=>0.5), t_bearing_distance( 0.0, 3.5, 1.6), -- << Default Constructor t_bearing_distance(p_sDegMinSec=>'43^01''21"', p_distance=>5.43, p_z=>2.0), t_bearing_distance(p_sDegMinSec=>'270', p_distance=>9.5, p_z=>0.5), t_bearing_distance(p_sDegMinSec=>'149^58''6.3"',p_distance=>4.613,p_z=>0.1)) ) .ST_Round(8,8) AS line FROM dual ) f; . VLINE LINE METERS ----- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------ TRUE SDO_GEOMETRY(3002,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,2,1),SDO_ORDINATE_ARRAY(0.0,3.5,0.0, 0.0,0.0,0.1, 3.5,0.0,0.5, 3.5,3.5,1.6, 7.20481032,7.46979603,2.0, -2.29518968,7.46979603,0.5, 0.01351213,3.47609287,0.1)) 30.39
ST_Line2COGO
This function starts with a single linestring (T_GEOMETRY) object, and constructs from it a set of bearings and distances.
CREATE OR REPLACE TYPE T_GEOMETRY AS ... . Member FUNCTION ST_Line2Cogo (p_unit IN varchar2 DEFAULT NULL) RETURN T_BEARING_DISTANCES Pipelined, . -- Examples -- Create 2D Line from COGO then reverse back to COGO .... WITH DATA AS ( SELECT f.line FROM (SELECT t_geometry(sdo_geometry(2001,NULL,sdo_point_type(0.0,3.5,NULL),NULL,NULL),0.005,2,1) .ST_Cogo2Line ( t_bearing_distances( t_bearing_distance(180.00,3.50,NULL), t_bearing_distance( 90.00,3.50,NULL), t_bearing_distance( 0.00,3.50,NULL), t_bearing_distance( 43.02,5.43,NULL), t_bearing_distance(270.00,9.50,NULL)) ) AS line FROM dual ) f ) SELECT COGO.DD2DMS(COGO.ST_Degrees(t.bearing)) AS bearing, Round(t.distance,3) AS distance FROM DATA a, TABLE(a.line.ST_Line2Cogo()) t; . BEARING DISTANCE -------- -------- 0�0'0" 3.5 180�0'0" 3.5 90�0'0" 3.5 0�0'0" 3.5 43�1'12" 5.43 270�0'0" 9.5 . 6 ROWS selected . -- Create 3D Line from COGO then reverse back to COGO .... WITH DATA AS ( SELECT f.line FROM (SELECT t_geometry(sdo_geometry(3001,NULL,sdo_point_type(0.0,3.5,0.2),NULL,NULL),0.005,2,1) .ST_Cogo2Line ( t_bearing_distances( t_bearing_distance(180.00,3.50,1.1), t_bearing_distance( 90.00,3.50,2.0), t_bearing_distance( 0.00,3.50,3.0), t_bearing_distance( 43.02,5.43,4.4), t_bearing_distance(270.00,9.50,5.2)) ) AS line FROM dual ) f ) SELECT COGO.DD2DMS(COGO.ST_Degrees(t.bearing)) AS bearing, Round(t.distance,3) AS distance, t.z FROM DATA a, TABLE(a.line.ST_Line2Cogo()) t; . BEARING DISTANCE Z -------- -------- --- 0�0'0" 3.506 0.2 180�0'0" 3.614 1.1 90�0'0" 3.614 2 0�0'0" 3.64 3 43�1'12" 5.608 4.4 270�0'0" 9.534 5.2 . 6 ROWS selected
ST_COGO2Polygon
This function, like ST_COGO2Line starts with a point (T_GEOMETRY) object, and constructs a polygon with a single exterior ring from the passed in set of bearings and distances. (A dedicated Constructor will be added at some stage to enable objects to be created from scratch.
CREATE OR REPLACE TYPE T_GEOMETRY AS ... Member FUNCTION ST_Cogo2Polygon(p_bearings_and_distances IN T_BEARING_DISTANCES) RETURN T_Geometry Deterministic, . -- Examples -- Polygon built from default constructor... SELECT F.poly.ST_Validate() AS vPoly, f.poly.ST_AsText() AS pWKT, round(f.Poly.ST_Area(),2) AS sqM FROM (SELECT t_geometry(sdo_geometry(2001,NULL,sdo_point_type(0,3.5,NULL),NULL,NULL),0.005,2,1) .ST_Cogo2Polygon( t_bearing_distances( t_bearing_distance(180,3.5,NULL), t_bearing_distance(90,3.5,NULL), t_bearing_distance(0,3.5,NULL), t_bearing_distance(43.02,5.43,NULL), t_bearing_distance(270,9.5,NULL)) ) .ST_Round(3,3) AS poly FROM dual ) f; . VPOLY PWKT SQM ----- -------------------------------------------------------------------------------- ----- TRUE POLYGON ((0.0 3.5, 0.0 0.0, 3.5 0.0, 3.5 3.5, 7.205 7.47, -2.295 7.47, 0.0 3.5)) 38.06 . -- Different way of building directions. -- Simple bearing/distance constructors used WITH DATA AS ( SELECT CAST(MULTISET( SELECT bd FROM (SELECT 1 AS rin, t_bearing_distance(180.0,3.5) AS bd FROM dual UNION ALL SELECT 2, t_bearing_distance( 90.0,3.5) FROM dual UNION ALL SELECT 3, t_bearing_distance( 0.0,3.5) FROM dual UNION ALL SELECT 4, t_bearing_distance(43.02,round(SQRT(4.5*4.5+2.2*4.2),2)) FROM dual UNION ALL SELECT 5, t_bearing_distance(270.0,(4.5+3.4+1.6)) FROM dual ) ORDER BY rin ) AS t_bearing_distances ) AS directions FROM dual ) SELECT F.poly.ST_Validate() AS vPoly, f.poly.ST_AsText() AS pWKT, round(f.Poly.ST_Area(),2) AS sqM FROM (SELECT t_geometry(sdo_geometry(2001,NULL,sdo_point_type(0,3.5,NULL),NULL,NULL),0.005,2,1) .ST_Cogo2Polygon ( p_bearings_and_distances=>a.directions ) .ST_Round(3,3) AS poly FROM DATA a ) f; . VPOLY PWKT SQM ----- -------------------------------------------------------------------------------- ----- TRUE POLYGON ((0.0 3.5, 0.0 0.0, 3.5 0.0, 3.5 3.5, 7.205 7.47, -2.295 7.47, 0.0 3.5)) 38.06 . -- Mixed Constructors with Z for 3D Polygon... SELECT F.poly.ST_Validate() AS vPoly, f.poly.geom AS polygon, round(f.Poly.ST_Area(),2) AS sqM FROM (SELECT t_geometry(sdo_geometry(3001,NULL,sdo_point_type(0,3.5,10.0),NULL,NULL),0.005,2,1) .ST_Cogo2Polygon ( t_bearing_distances( t_bearing_distance(180,3.5,11.1), t_bearing_distance(p_sDegMinSec=>'90^0''0"',p_distance=>3.5,p_z=>12.2), t_bearing_distance(0.0,3.5,13.3), t_bearing_distance(p_sDegMinSec=>'43^01''12"',p_distance=>5.43,p_z=>14.4), t_bearing_distance(270.0,9.5,13.3) ) ) .ST_Round(3,3) AS poly FROM dual ) f; . VPOLY POLYGON SQM ----- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----- TRUE SDO_GEOMETRY(3003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(0.0,3.5,10.0, 0.0,0.0,11.1, 3.5,0.0,12.2, 3.5,3.5,13.3, 7.205,7.47,14.4, -2.295,7.47,13.3, 0.0,3.5,10.0)) 43.37
I am considering adding a traverse adjustment option (p_traverse_adjust) to the creation of a polygon exterior ring.
I hope these will be of interest 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