[postgis-users] Degrees of a linestring segment

Bruce Rindahl rindahl at lrcwe.com
Fri Apr 27 08:25:13 PDT 2007


Flavio
This will not work because line_interpolate_point and line_locate_point do
not give the vertex locations, only points and locations along the line.
Say you have a linestring with three segments (and four points).  If you use
line_locate_point(the_line,my_point) where my_line is your line and my_point
is your point that is close to the middle of the line, the result will be
0.5 or half way along the line.  It will not tell you which vertex it is
closest to.  It you then use line_interpolate_point(my_line,0.5) you will
get a new point halfway along your line or in the middle of the middle
segment.
The good news is it can be done with a new function called
line_locate_vertex(linestring,point) that will give you the closest vertex
to the point.  I wrote this to split polygons into four sides for section
lines recently.  The function is:
--------------------------------------------------------------------------

-- Function: line_locate_vertex(geometry, geometry)

-- DROP FUNCTION line_locate_vertex(geometry, geometry);

CREATE OR REPLACE FUNCTION line_locate_vertex(geometry, geometry)
  RETURNS integer AS
$BODY$
  DECLARE     
	dist double precision;
	n_dist double precision;
	i integer;
	p integer;
  BEGIN
	dist = 9999999999999;
     
   IF (GeometryType($1) != 'LINESTRING') THEN
	raise notice 'First Geometry type must be a LINESTRING';
	RETURN -1;
   END IF;
   IF (GeometryType($2) != 'POINT') THEN
	raise notice 'Second Geometry type must be a POINT';
	RETURN -1;
   END IF;

	FOR i IN 1 .. numPoints($1)
	LOOP
		n_dist = distance($2,pointN($1,i));
		IF (n_dist < dist) THEN
			p = i;
			dist = n_dist;
		END IF;
	END LOOP;

    RETURN p;
  
  END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION line_locate_vertex(geometry, geometry) OWNER TO postgres;

-------------------------------------------------------------------------

Using this function, the result of line_locate_vertex(my_line,my_point) will
give the index of the vertex closest to your point.  You then have to figure
out if you need the next vertex or the previous vertex for your line
segment.  This can be done using line_locate_point.  First get the location
your closest vertex along the line:

	index = line_locate_vertex(my_line,my_point)

Then find the location of that vertex along the line:

	indx_loc = line_locate_point(pointN(my_line,index))

Then find the location of your point along the line:

	pnt_loc = line_locate_point(my_line,my_point)

If pn_loc is less than indx_loc your line segment goes from
pointN(my_line,index-1) to pointN(my_line,index).

If pn_loc is greater than indx_loc your line segment goes from
pointN(my_line,index) to pointN(my_line,index+1).

Hope this helps!

Bruce Rindahl

 

-----Original Message-----
From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net] On Behalf Of Flavio
Perri
Sent: Friday, April 27, 2007 3:26 AM
To: postgis-users at postgis.refractions.net
Subject: [postgis-users] Degrees of a linestring segment


Hi all, i'm trying to calculate the degrees of a linestring, but i need the
degree of the closest segment that contains a point. I explain better.

I have a point near a line. I use the line_interpolate_point() and
line_locate_point() to locate the point on the linestring. Then I make two
segments with Makeline from the linestring:
1) StartPoint - interpolated point
2) (Interpolated point+1) - EndPoint

With PointN() i get the (n-1)th point of (1) and the first point of (2) and
finally i can call degrees(azimuth(P1,P2)) to retrieve the degrees.

Is this way ok? The fact is that sometime the return value is NULL because
the two points are the same.

This is the query i used:

      SELECT
degrees(azimuth(PointN(MakeLine(StartPoint(l.the_geom),line_interpolate_poin
t(l.the_geom,
 line_locate_point(l.the_geom,
a.point_geom))),(numPoints(MakeLine(StartPoint(l.the_geom),line_interpolate_
point(l.the_geom,
 line_locate_point(l.the_geom,
a.point_geom))))-1)),PointN(MakeLine(line_interpolate_point(l.the_geom,
line_locate_point(l.the_geom, a.point_geom)), EndPoint(l.the_geom)),1))) as
degrees from pointTable a, LineTable l

Bye,
Flavio

_______________________________________________
postgis-users mailing list
postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users






More information about the postgis-users mailing list