You could accomplish this a few different ways depending on what sort of output you are wanting, but the concept is the same. It's generally easier to do a simple rotation followed by a translation rather than trying to calculate the coordinates in a single step.
In this case, the basic steps are:
- Create a line of the desired length at the origin (0,0). This line should run along the axis that you wish to measure your angle from and have it's center at the origin.
- Rotate the line around the origin.
- Translate the line by the coordinates of the point that you want it to be centered on.
The following PostGIS view creates the lines from your example scenario. A few things are assumed:
- The geometry column is called
shape
- The angle is measured from the x axis. Your example drawing was a bit confusing since you first mentioned 40 degrees, drew a dotted vertical line, but then said it should be around 160 degrees. I've interpreted that to mean you actually want to measure from the x axis.
The data is projected in the same units that you want to measure with (ie. meters).
CREATE OR REPLACE VIEW <viewname> AS
WITH vertices AS
(SELECT
objectid,
(ST_DumpPoints(shape)).path[1] AS v_id,
(ST_DumpPoints(shape)).geom AS vertex
FROM <source_data>
)
SELECT
objectid,
v_id,
ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 1.0,0.0),
ST_MakePoint(-1.0,0.0)),
radians(40)), ST_X(vertex), ST_Y(Vertex)),
ST_SRID(vertex)) AS newline
FROM vertices
To break down what's actually going on with that last line, starting from the inner most:
ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 0,1.0),
ST_MakePoint(0,-1.0)),
radians(40)), ST_X(vertex), ST_Y(Vertex)),
ST_SRID(vertex)) AS newline
ST_MakePoint(1.0,0.0)
and ST_MakePoint(-1.0,0.0)
: Create the endpoints for a horizontal line that is our desired length and centered on the origin.
ST_MakeLine(...)
: Use our newly created end points to create a line.
ST_Rotate(..., radians(40))
: Rotate that new line around the origin.
ST_Translate(..., ST_X(vertex), ST_Y(vertex))
: Center the rotated line onto our reference (input) point.
ST_SetSRID(..., ST_SRID(vertex))
: Give the new line the same SRID as the input geometry.
If you are using PostGIS 2.0 you can simplify this since you can specify a different origin for ST_Rotate
.
If you want to rotate to an angle based on the slope of the line, you'll have to calculate that first and add it to the rotation angle.
If the data isn't projected in the same units that you want to measure in you can still do something similar, but you'll need an extra step:
- Create a line (projected in something that uses what you want to measure in)
- Rotate
- Reproject to your target projection
- Translate to the target point
Edit
I now understand what you mean by the angle. Essentially, you want a rotation clockwise from the Y axis (0 is up, 90 is right, 180 is down, etc.).
You do still need to use the radians
function since ST_Rotate
expect the angle in radians. You should be able to get the correct angle with two small changes:
- Start with a vertical line (use
ST_MakePoint(0.0,1.0)
and ST_MakePoint(0.0,-1.0)
)
- Multiply your angle by -1. This will make it negative, causing
ST_rotate
to rotate it in a clockwise direction. radians(<angle> * -1)