From: Paul Ramsey Date: Wed, 1 Feb 2012 21:27:01 +0000 (+0000) Subject: Enhance ST_Rotate by adding offset origin parameters (#1251) from mwtoews X-Git-Tag: 2.0.0alpha4~98 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f7d7ff0d13bc34061f087aae78f6069e9d933c2;p=postgis Enhance ST_Rotate by adding offset origin parameters (#1251) from mwtoews git-svn-id: http://svn.osgeo.org/postgis/trunk@9006 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/reference_editor.xml b/doc/reference_editor.xml index 5577c5cdc..15a1721d5 100644 --- a/doc/reference_editor.xml +++ b/doc/reference_editor.xml @@ -143,11 +143,11 @@ z' = z This method is a subcase of the 3D method Examples ---Rotate a 3d line 180 degrees about the z axis. Note this is long-hand for doing ST_RotateZ(); +--Rotate a 3d line 180 degrees about the z axis. Note this is long-hand for doing ST_Rotate(); SELECT ST_AsEWKT(ST_Affine(the_geom, cos(pi()), -sin(pi()), 0, sin(pi()), cos(pi()), 0, 0, 0, 1, 0, 0, 0)) As using_affine, - ST_AsEWKT(ST_RotateZ(the_geom, pi())) As using_rotatez + ST_AsEWKT(ST_Rotate(the_geom, pi())) As using_rotate FROM (SELECT ST_GeomFromEWKT('LINESTRING(1 2 3, 1 4 3)') As the_geom) As foo; - using_affine | using_rotatez + using_affine | using_rotate -----------------------------+----------------------------- LINESTRING(-1 -2 3,-1 -4 3) | LINESTRING(-1 -2 3,-1 -4 3) (1 row) @@ -155,11 +155,10 @@ z' = z This method is a subcase of the 3D method --Rotate a 3d line 180 degrees in both the x and z axis SELECT ST_AsEWKT(ST_Affine(the_geom, cos(pi()), -sin(pi()), 0, sin(pi()), cos(pi()), -sin(pi()), 0, sin(pi()), cos(pi()), 0, 0, 0)) FROM (SELECT ST_GeomFromEWKT('LINESTRING(1 2 3, 1 4 3)') As the_geom) As foo; - st_asewkt + st_asewkt ------------------------------- LINESTRING(-1 -2 -3,-1 -4 -3) (1 row) - @@ -825,7 +824,7 @@ LINESTRING(1 2,1 10) | LINESTRING(1 10,1 2) ST_Rotate - This is a synonym for ST_RotateZ + Rotate a geometry rotRadians counter-clockwise about an origin. @@ -833,17 +832,35 @@ LINESTRING(1 2,1 10) | LINESTRING(1 10,1 2) geometry ST_Rotate geometry geomA - float rotZRadians + float rotRadians + + + geometry ST_Rotate + geometry geomA + float rotRadians + float x0 + float y0 + + + + geometry ST_Rotate + geometry geomA + float rotRadians + geometry pointOrigin + Description - This is a synonym for ST_RotateZ.. Rotates geometry rotZRadians about the Z-axis. + Rotates geometry rotRadians counter-clockwise about the origin. The rotation origin can be + specified either as a POINT geometry, or as x and y coordinates. If the origin is not + specified, the geometry is rotated about POINT(0 0). Enhanced: 2.0.0 support for Polyhedral surfaces, Triangles and TIN was introduced. + Enhanced: 2.0.0 additional parameters for specifying the origin of rotation were added. Availability: 1.1.2. Name changed from Rotate to ST_Rotate in 1.2.2 &Z_support; &curve_support; @@ -856,7 +873,29 @@ LINESTRING(1 2,1 10) | LINESTRING(1 10,1 2) Examples - + +--Rotate 180 degrees +SELECT ST_AsEWKT(ST_Rotate('LINESTRING (50 160, 50 50, 100 50)', pi())); + st_asewkt +--------------------------------------- + LINESTRING(-50 -160,-50 -50,-100 -50) +(1 row) + +--Rotate 30 degrees counter-clockwise at x=50, y=160 +SELECT ST_AsEWKT(ST_Rotate('LINESTRING (50 160, 50 50, 100 50)', pi()/6, 50, 160)); + st_asewkt +--------------------------------------------------------------------------- + LINESTRING(50 160,105 64.7372055837117,148.301270189222 89.7372055837117) +(1 row) + +--Rotate 60 degrees clockwise from centroid +SELECT ST_AsEWKT(ST_Rotate(geom, -pi()/3, ST_Centroid(geom))) +FROM (SELECT 'LINESTRING (50 160, 50 50, 100 50)'::geometry AS geom) AS foo; + st_asewkt +-------------------------------------------------------------- + LINESTRING(116.4225 130.6721,21.1597 75.6721,46.1597 32.3708) +(1 row) + @@ -998,6 +1037,7 @@ SELECT ST_AsEWKT(ST_RotateX(ST_GeomFromEWKT('LINESTRING(1 2 3, 1 1 1)'), pi()/2) Rotate a geometry geomA - rotRadians about the Z axis. + This is a synonym for ST_Rotate ST_RotateZ(geomA, rotRadians) is short-hand for SELECT ST_Affine(geomA, cos(rotRadians), -sin(rotRadians), 0, sin(rotRadians), cos(rotRadians), 0, 0, 0, 1, 0, 0, 0). diff --git a/postgis/postgis.sql.in.c b/postgis/postgis.sql.in.c index 01dad6f29..5db961d93 100644 --- a/postgis/postgis.sql.in.c +++ b/postgis/postgis.sql.in.c @@ -115,6 +115,33 @@ CREATE CAST (geometry AS geometry) WITH FUNCTION geometry(geometry, integer, boo ------------------------------------------------------------------- -- BOX3D TYPE +-- Point coordinate data access +------------------------------------------- +-- PostGIS equivalent function: X(geometry) +CREATE OR REPLACE FUNCTION ST_X(geometry) + RETURNS float8 + AS 'MODULE_PATHNAME','LWGEOM_x_point' + LANGUAGE 'C' IMMUTABLE STRICT; + +-- PostGIS equivalent function: Y(geometry) +CREATE OR REPLACE FUNCTION ST_Y(geometry) + RETURNS float8 + AS 'MODULE_PATHNAME','LWGEOM_y_point' + LANGUAGE 'C' IMMUTABLE STRICT; + +-- Availability: 1.2.2 +CREATE OR REPLACE FUNCTION ST_Z(geometry) + RETURNS float8 + AS 'MODULE_PATHNAME','LWGEOM_z_point' + LANGUAGE 'C' IMMUTABLE STRICT; + +-- Availability: 1.2.2 +CREATE OR REPLACE FUNCTION ST_M(geometry) + RETURNS float8 + AS 'MODULE_PATHNAME','LWGEOM_m_point' + LANGUAGE 'C' IMMUTABLE STRICT; + +------------------------------------------- ------------------------------------------------------------------- CREATE OR REPLACE FUNCTION box3d_in(cstring) @@ -679,15 +706,27 @@ CREATE OR REPLACE FUNCTION ST_Affine(geometry,float8,float8,float8,float8,float8 LANGUAGE 'SQL' IMMUTABLE STRICT; -- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_RotateZ(geometry,float8) +CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8) RETURNS geometry AS 'SELECT ST_Affine($1, cos($2), -sin($2), 0, sin($2), cos($2), 0, 0, 0, 1, 0, 0, 0)' LANGUAGE 'SQL' IMMUTABLE STRICT; +-- Availability: 2.0.0 +CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,float8,float8) + RETURNS geometry + AS 'SELECT ST_Affine($1, cos($2), -sin($2), 0, sin($2), cos($2), 0, 0, 0, 1, $3 - cos($2) * $3 + sin($2) * $4, $4 - sin($2) * $3 - cos($2) * $4, 0)' + LANGUAGE 'SQL' IMMUTABLE STRICT; + +-- Availability: 2.0.0 +CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,geometry) + RETURNS geometry + AS 'SELECT ST_Affine($1, cos($2), -sin($2), 0, sin($2), cos($2), 0, 0, 0, 1, ST_X($3) - cos($2) * ST_X($3) + sin($2) * ST_Y($3), ST_Y($3) - sin($2) * ST_X($3) - cos($2) * ST_Y($3), 0)' + LANGUAGE 'sql' IMMUTABLE STRICT; + -- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8) +CREATE OR REPLACE FUNCTION ST_RotateZ(geometry,float8) RETURNS geometry - AS 'SELECT ST_RotateZ($1, $2)' + AS 'SELECT ST_Rotate($1, $2)' LANGUAGE 'SQL' IMMUTABLE STRICT; -- Availability: 1.2.2 @@ -3464,30 +3503,6 @@ CREATE OR REPLACE FUNCTION ST_PatchN(geometry, integer) ' LANGUAGE 'SQL' IMMUTABLE STRICT; --- PostGIS equivalent function: X(geometry) -CREATE OR REPLACE FUNCTION ST_X(geometry) - RETURNS float8 - AS 'MODULE_PATHNAME','LWGEOM_x_point' - LANGUAGE 'C' IMMUTABLE STRICT; - --- PostGIS equivalent function: Y(geometry) -CREATE OR REPLACE FUNCTION ST_Y(geometry) - RETURNS float8 - AS 'MODULE_PATHNAME','LWGEOM_y_point' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_Z(geometry) - RETURNS float8 - AS 'MODULE_PATHNAME','LWGEOM_z_point' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_M(geometry) - RETURNS float8 - AS 'MODULE_PATHNAME','LWGEOM_m_point' - LANGUAGE 'C' IMMUTABLE STRICT; - -- PostGIS equivalent function of old StartPoint(geometry)) CREATE OR REPLACE FUNCTION ST_StartPoint(geometry) RETURNS geometry @@ -4626,7 +4641,7 @@ $BODY$ -- Compute the midpoint p1 = ST_line_interpolate_point(l1,0.5); -- Rotate the line 90 degrees around the midpoint (perpendicular bisector) - l1 = ST_Translate(ST_Rotate(ST_Translate(l1,-ST_X(p1),-ST_Y(p1)),pi()/2),ST_X(p1),ST_Y(p1)); + l1 = ST_Rotate(l1,pi()/2,p1); -- Compute the azimuth of the bisector a1 = ST_Azimuth(ST_PointN(l1,1),ST_PointN(l1,2)); -- Extend the line in each direction the new computed distance to insure they will intersect @@ -4636,7 +4651,7 @@ $BODY$ -- Repeat for the line from the point to the other diameter point l2 = ST_Makeline(ST_PointN(ring,idx2),ST_PointN(ring,k)); p2 = ST_Line_interpolate_point(l2,0.5); - l2 = ST_Translate(ST_Rotate(ST_Translate(l2,-ST_X(p2),-ST_Y(p2)),pi()/2),ST_X(p2),ST_Y(p2)); + l2 = ST_Rotate(l2,pi()/2,p2); a2 = ST_Azimuth(ST_PointN(l2,1),ST_PointN(l2,2)); l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,2))+sin(a2)*dist,ST_Y(ST_PointN(l2,2))+cos(a2)*dist),-1); l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,1))-sin(a2)*dist,ST_Y(ST_PointN(l2,1))-cos(a2)*dist),0); diff --git a/regress/affine.sql b/regress/affine.sql index e1f18d218..1d5ef0999 100644 --- a/regress/affine.sql +++ b/regress/affine.sql @@ -9,6 +9,12 @@ select 'ST_Scale', ST_asewkt(ST_Scale('POINT(1 1)'::geometry, 5, 5)); select 'ST_Scale', ST_asewkt(ST_Scale('POINT(1 1)'::geometry, 3, 2)); select 'ST_Scale', ST_asewkt(ST_Scale('POINT(10 20 -5)'::geometry, 4, 2, -8)); +-- ST_Rotate +select 'ST_Rotate', ST_asewkt(ST_SnapToGrid(ST_Rotate('POINT(1 1)'::geometry, pi()/2, 10.0, 20.0), 0.1)); +select 'ST_Rotate', ST_asewkt(ST_SnapToGrid(ST_Rotate('POINT(1 1)'::geometry, -pi()/2, -1.0, 2.0), 0.1)); +select 'ST_Rotate', ST_asewkt(ST_SnapToGrid(ST_Rotate('POINT(1 1)'::geometry, pi()/2, 'POINT(10 10)'::geometry), 0.1)); +select 'ST_Rotate', ST_asewkt(ST_SnapToGrid(ST_Rotate('POINT(1 1)'::geometry, pi()/2, ST_Centroid('LINESTRING(0 0, 1 0)'::geometry)), 0.1)); + -- ST_RotateZ select 'ST_RotateZ', ST_asewkt(ST_SnapToGrid(ST_RotateZ('POINT(1 1)'::geometry, pi()), 0.1)); select 'ST_RotateZ', ST_asewkt(ST_SnapToGrid(ST_RotateZ('POINT(1 1)'::geometry, pi()/2), 0.1)); diff --git a/regress/affine_expected b/regress/affine_expected index 5e918b9a3..639d06983 100644 --- a/regress/affine_expected +++ b/regress/affine_expected @@ -3,6 +3,10 @@ ST_Translate|POINT(-3 -7 3) ST_Scale|POINT(5 5) ST_Scale|POINT(3 2) ST_Scale|POINT(40 40 40) +ST_Rotate|POINT(29 11) +ST_Rotate|POINT(-2 0) +ST_Rotate|POINT(19 1) +ST_Rotate|POINT(-0.5 0.5) ST_RotateZ|POINT(-1 -1) ST_RotateZ|POINT(-1 1) ST_RotateZ|POINT(1 -1)