[postgis-users] st_distance accuracy?
Sufficool, Stanley
ssufficool at sbcounty.gov
Tue Oct 20 14:48:23 PDT 2009
Following the KISS principle helps sometimes:
CREATE OR REPLACE FUNCTION st_line_interpolate_point(m_geom geometry, m_percent double precision, m_offset double precision)
RETURNS geometry AS
$BODY$
declare m_seg geometry;
declare p1 geometry;
declare p2 geometry;
BEGIN
m_seg := st_line_substring(m_geom, 0, m_percent);
p1:=st_pointn(m_seg, st_npoints(m_seg)-1);
p2:=st_pointn(m_seg, st_npoints(m_seg));
/* get the delta of the line segment and offset the interpolated point */
/* Rotate deltas by 90 degrees (invert dx/dy ) */
return st_translate(
st_line_interpolate_point(m_geom, m_percent),
((st_y(p2) - st_y(p1)) / st_distance(p1,p2)) * m_offset,
((st_x(p2) - st_x(p1)) / st_distance(p1,p2)) * (-m_offset)
);
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION st_line_interpolate_point(geometry, double precision, double precision) OWNER TO postgres;
> -----Original Message-----
> From: postgis-users-bounces at postgis.refractions.net
> [mailto:postgis-users-bounces at postgis.refractions.net] On
> Behalf Of Nicklas Avén
> Sent: Tuesday, October 20, 2009 2:29 PM
> To: PostGIS Users Discussion
> Subject: Re: [postgis-users] st_distance accuracy?
>
>
> Sorry wrong thinking from me in last post. But look at it
> again. You are not measuring along the line but strait from
> first vertex to each of the others. /nicklas
>
> -- originalmedd. --
> Ämne: Re: [postgis-users] st_distance accuracy?
> Från: nicklas.aven at jordogskog.no
> Datum: 2009-10-20 23:14
>
> To find the last two vertexes why not use:
> p1:=st_pointn(m_geom,ST_NPoints(m_geom)-1);
> p2:=st_pointn(m_geom,ST_NPoints(m_geom));
> /Nicklas
>
>
>
> 2009-10-20 nicklas.aven at jordogskog.no wrote:
>
> I'm not sure I understand what you are trying to do. But as I
> read it you are comparing the length of the line with the
> >straight distance from the first to one and each of the
> following vertexes. > >Is that really what you want?>
> >Nothing says that the last vertex is the one most far away
> from the first and the only case when that distance is the
> same as the length of the line is if the line is straight.
> >> >Or am I missunderstanding you?> >/Nicklas> > >
> > 2009-10-20 Sufficool Stanley wrote:
> >
> > I am attempting to get the last vertex index of a line for a given
> > >measure using the following:
> > >
> > >idx := max(np) from generate_series(1,st_npoints(m_geom))
> as np where
> > >st_distance(st_pointn(m_geom,1), st_pointn(m_geom,np)) <=
> > >m_distance;
> > >
> > >However, some of my queries are returning the last point on the
> > >linestring when "m_distance" is less than the st_length() of the
> > >given geometry.
> > >
> > >Is this an issue with st_distance? I don't get the same issue when
> > >using Lat/Lon and st_distance_spheroid().
> > >
> > >select postgis_version()
> > >1.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
> > >
> > >select version()
> > >PostgreSQL 8.4.0, compiled by Visual C++ build 1400, 32-bit
> > >
> > >
> > >FULL FUNCTION TEXT
> > >------------------------
> > >CREATE OR REPLACE FUNCTION
> st_line_interpolate_point(m_geom geometry,
> > >m_percent double precision, m_offset double precision) RETURNS
> > >geometry AS $BODY$
> > >
> > >declare idx int;
> > >declare m_distance double precision;
> > >declare p1 geometry;
> > >declare p2 geometry;
> > >
> > >BEGIN
> > >
> > >IF (m_distance > 1 or m_distance < 0) THEN
> > > raise exception 'Percentage must be between 0 and 1';
> > >END IF;
> > >
> > >/* Convert percentage to actual distance measure */ m_distance :=
> > >st_length(m_geom) * m_percent;
> > >
> > >/* Get the last point number on the line that is less than the
> > >requested distance */
> > >
> > >/* For Feet (NAD1983) */
> > >idx := max(np) from generate_series(1,st_npoints(m_geom))
> as np where
> > >st_distance(st_pointn(m_geom,1), st_pointn(m_geom,np)) <=
> > >m_distance;
> > >
> > >/* For Lat/Long (TIGER Lines) */
> > >--idx := max(np) from generate_series(1,st_npoints(m_geom)) as np
> > >where st_distance_sphere(st_pointn(m_geom,1),
> st_pointn(m_geom,np))
> > >< m_distance;
> > >
> > >/* Past the end of the line segment return exception (this should
> > >never
> > >happen) */
> > >if idx = st_npoints(m_geom) then
> > > raise exception 'st_line_interpolate_point(geom, dbl,
> dbl): Attempt to
> > >seek beyond end of line.';
> > >end if;
> > >
> > >/* Grab the 2 points of the matching line segment */
> > >p1:=st_pointn(m_geom,idx); p2:=st_pointn(m_geom,idx + 1);
> > >
> > >/* get the delta of the line segment and offset the interpolated
> > >point */
> > >/* Rotate deltas by 90 degrees (invert dx/dy ) */
> > >/* spheroid projections will need the offset to vary based
> on lat/lon
> > >*/ return st_translate( line_interpolate_point(m_geom, m_percent),
> > > ((st_y(p2) - st_y(p1)) / st_distance(p1,p2)) * m_offset,
> > > ((st_x(p2) - st_x(p1)) / st_distance(p1,p2)) * (-m_offset)
> > >);
> > >
> > >END;
> > >
> > >$BODY$
> > > LANGUAGE 'plpgsql' VOLATILE
> > > COST 100;
> > >ALTER FUNCTION st_line_interpolate_point(geometry, double
> precision,
> > >double precision) OWNER TO postgres;
> > >
> > >_______________________________________________
> > >postgis-users mailing list postgis-users at postgis.refractions.net
> > >postgis.refractions.net/mailman/listinfo/postgis-users
> > >
> > >
>
> _______________________________________________
> postgis-users mailing list postgis-users at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-users
>
>
> _______________________________________________
> 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