[postgis-devel] Rotate functions

Mike Toews mwtoews at sfu.ca
Mon Jan 25 00:18:28 PST 2010

```Hi,

I'm not sure if anyone has inspected the Rotate functions closely, but
they are vaguely documented. Specifically, they don't specify the origin
of the axis of rotation in the docs. Intuitively, one could assume it
would be the centroid of the feature (as graphics programs, such as
ArcGIS or Adobe Illustrator might have us think), but it is actually the
absolute origin (0 0) ... as in latitude 0 or northing 0 m, etc.

The fundamentals of rotating objects in 2D requires two pieces of
information: (1) the origin or coordinate of the axis of rotation; and
(2) a rotation angle. These are required by CAD programs, and the origin
of rotation is often adjustable in many graphics programs. However,
ST_Rotate (et al.) only offer the rotation angle. I would expect the
[ST_RotateZ] function to have two alternative definitions:

geometry ST_Rotate(geometry geomA, float x0, float y0, float rotRadians);
-- or --
geometry ST_Rotate(geometry geomA, geometry axisOrig, float rotRadians);

To apply some trigonometry to PostGIS, we can use the affine function
with some modified offsets (not 0). Consider a polygon 'geom', rotated
from (11 10) by -270 degrees:

FROM (select 'POLYGON((10 10, 11 10, 11 11, 10 10))'::geometry as geom,
-270*2*pi()/360 as rad, 11 as X0, 10 as Y0) AS foo;

POLYGON((11 9,11 10,10 10,11 9))

This could be defined in the definitions described above as the
following functions:

-- geometry ST_Rotate(geometry geomA, float x0, float y0, float rotRadians);
CREATE OR REPLACE FUNCTION st_rotate(geometry, double precision, double
precision, double precision)
RETURNS geometry AS
'SELECT affine(\$1, cos(\$4), -sin(\$4), 0, sin(\$4), cos(\$4), 0, 0, 0, 1,
\$2-cos(\$4)*\$2+sin(\$4)*\$3, \$3-sin(\$4)*\$2-cos(\$4)*\$3, 0)' LANGUAGE 'sql'
IMMUTABLE STRICT COST 100;

-- select asewkt(st_rotate('POLYGON((10 10, 11 10, 11 11, 10
10))'::geometry, 11, 10, -270*2*pi()/360));

-- or --

-- geometry ST_Rotate(geometry geomA, geometry axisOrig, float rotRadians);
CREATE OR REPLACE FUNCTION st_rotate(geometry, geometry, double precision)
RETURNS geometry AS
'SELECT affine(\$1, cos(\$3), -sin(\$3), 0, sin(\$3), cos(\$3), 0, 0, 0, 1,
st_x(\$2)-cos(\$3)*st_x(\$2)+sin(\$3)*st_y(\$2),
st_y(\$2)-sin(\$3)*st_x(\$2)-cos(\$3)*st_y(\$2), 0)' LANGUAGE 'sql' IMMUTABLE
STRICT COST 100;

-- select asewkt(st_rotate('POLYGON((10 10, 11 10, 11 11, 10
10))'::geometry, 'POINT(11 10)'::geometry, -270*2*pi()/360));

I'd pick the second of the two if I could make a decision on which to
keep/loose.

Also, I figure it is for mathematical completeness, but why does the
standard PostGIS install include rotateX and rotateY in the SQL
functions? I consider this bloat, since I don't see who would use it
(especially since they are all from x/y/z=0)? Primarily, GIS folk view
maps from above. As a geologist, I often use depth in my day-to-day
work, but I'd rarely see a need for rotating on anything but Z. Should
these other rotation functions be deprecated and removed in a future
release? As they depend on affine, they can always be included on a Wiki
for odd-ball future reference, as they could always be in demand by
someone for some purpose. But the same could be said for rotating on
arbitrary XZ and YZ axes using similar functions as above for XY-plane
rotations.

-Mike

```