[postgis-users] ST_Intersects of a diagonal buffer on a polygon grid
Simon Greener
simon at spatialdbadvisor.com
Fri Jan 30 19:29:13 PST 2009
Michael,
I had a quick look at this and decided to tackle the problem slightly differently. What I did was take your diagonal line and break it up into "vectors" (ie two point line segments) which I then buffered and segmentized and inserted into your table. The changed section of your script is:
insert into throwaway_polybuff(the_geom)
select ST_Segmentize(ST_Buffer(ST_MakeLine(ST_MakePoint((startcoord).x,(startcoord).y),
ST_MakePoint((endcoord).x,(endcoord).y)), 1000), 5000) as the_geom
from GetVectorViaSQL('LINESTRING(200 403000,186000 367000,254000 134000,424000 23000,424000 23000)'::geometry) as p;
SELECT g.*
-- The Query --
-- Returns 2076 polygons but only 2095 with modified polybuff
-- Takes about 60 seconds on my computer (and 45 on mine)
-- but with the modified data it takes where now it take 3.3seconds
FROM throwaway_grid g,
throwaway_polybuff p
WHERE ST_Intersects(g.the_geom,p.the_geom);
SELECT g.*
-- Returns 2095 polygons
-- With this one taking 17 seconds
FROM throwaway_grid g,
(select ST_Segmentize(ST_Buffer(ST_MakeLine(ST_MakePoint((startcoord).x,(startcoord).y),
ST_MakePoint((endcoord).x,(endcoord).y)), 1000), 5000) as the_geom
from GetVectorViaSQL('LINESTRING(200 403000,186000 367000,254000 134000,424000 23000,424000 23000)'::geometry) ) as p
WHERE ST_Intersects(g.the_geom,p.the_geom );
The GetVector PgPLSQL function is:
CREATE OR REPLACE FUNCTION GetVectorViaSQL(p_geometry geometry)
RETURNS SETOF VectorType IMMUTABLE
AS $$
DECLARE
v_GeometryType varchar(1000);
v_rec RECORD;
v_vector VectorType;
v_start CoordType;
v_end CoordType;
c_linestring CURSOR ( p_geom geometry )
IS
SELECT X(sp) as sx,Y(sp) as sy,Z(sp) as sz,M(sp) as sm,X(ep) as ex,Y(ep) as ey,Z(ep) as ez,M(ep) as em
FROM ( SELECT pointn(p_geom, generate_series(1, npoints(p_geom)-1)) as sp,
pointn(p_geom, generate_series(2, npoints(p_geom) )) as ep
) AS foo;
c_multilinestring CURSOR ( p_geom geometry )
IS
SELECT X(sp),Y(sp),Z(sp),M(sp),X(ep),Y(ep),Z(ep),M(ep)
FROM ( SELECT pointn(b.geom, generate_series(1, npoints(b.geom)-1)) as sp,
pointn(b.geom, generate_series(2, npoints(b.geom) )) as ep
FROM (select geometryn(p_geom,generate_series(1,numgeometries(p_geom))) as geom) as b
) AS foo;
c_polygon CURSOR ( p_geom geometry )
IS
SELECT X(sp),Y(sp),Z(sp),M(sp),X(ep),Y(ep),Z(ep),M(ep)
FROM ( SELECT pointn(a.geom, generate_series(1, npoints(a.geom)-1)) as sp,
pointn(a.geom, generate_series(2, npoints(a.geom) )) as ep
FROM ( SELECT exteriorring(p_geom) as geom
UNION ALL
SELECT interiorringn(p_geom,generate_series(1,numinteriorrings(p_geom))) as geom
) a
) b;
c_multipolygon CURSOR ( p_geom geometry )
IS
SELECT X(sp),Y(sp),Z(sp),M(sp),X(ep),Y(ep),Z(ep),M(ep)
FROM ( SELECT pointn(a.geom, generate_series(1, npoints(a.geom)-1)) as sp,
pointn(a.geom, generate_series(2, npoints(a.geom) )) as ep
FROM ( SELECT exteriorring(b.geom) as geom
FROM (select geometryn(p_geom,generate_series(1,numgeometries(p_geom))) as geom ) b
UNION ALL
SELECT interiorringn(c.geom,generate_series(1,numinteriorrings(c.geom))) as geom
FROM (select geometryn(p_geom,generate_series(1,numgeometries(p_geom))) as geom ) c
) a
) b;
c_refcursor refcursor;
Begin
If ( p_geometry is NULL ) Then
return;
End If;
v_GeometryType := ST_GeometryType(p_geometry);
If ( v_GeometryType in ('ST_Point','ST_MultiPoint') ) Then
return;
End If;
IF ( v_GeometryType = 'ST_MultiLineString' ) THEN
OPEN c_multilinestring(p_geometry);
c_refcursor := c_multilinestring;
ELSIF ( v_GeometryType = 'ST_LineString' ) THEN
OPEN c_linestring(p_geometry);
c_refcursor := c_linestring;
ELSIF ( v_GeometryType = 'ST_MultiPolygon' ) THEN
OPEN c_multipolygon(p_geometry);
c_refcursor := c_multipolygon;
ELSIF ( v_GeometryType = 'ST_Polygon' ) THEN
OPEN c_polygon(p_geometry);
c_refcursor := c_polygon;
ELSIF ( v_GeometryType = 'ST_Geometry' ) THEN
-- COuld be anything... use native PostGIS function
v_GeometryType = GeometryType(p_geometry);
IF ( v_geometryType = 'GEOMETRYCOLLECTION' ) THEN
FOR v_geom IN 1..ST_NumGeometries(p_geometry) LOOP
FOR v_rec IN SELECT * FROM GetVectorViaSQL(ST_GeometryN(p_geometry,v_geom)) LOOP
RETURN NEXT v_rec;
END LOOP;
END LOOP;
ELSE
-- Probably CURVED something...
RETURN;
END IF;
END IF;
IF ( v_geometryType NOT IN ('ST_Geometry','GEOMETRYCOLLECTION') ) THEN
LOOP
FETCH c_refcursor INTO
v_start.x, v_start.y, v_start.z, v_start.m,
v_end.x, v_end.y, v_end.z, v_end.m;
v_vector.startcoord := v_start;
v_vector.endcoord := v_end;
EXIT WHEN NOT FOUND;
RETURN NEXT v_vector;
END LOOP;
CLOSE c_refcursor;
END IF;
end;
$$ LANGUAGE 'plpgsql';
regards
Simon
--
SpatialDB Advice and Design, Solutions Architecture and Programming,
Oracle Database 10g Administrator Certified Associate; Oracle Database 10g SQL Certified Professional
Oracle Spatial, SQL Server, PostGIS, MySQL, ArcSDE, Manifold GIS, Radius Topology and Studio Specialist.
39 Cliff View Drive, Allens Rivulet, 7150, Tasmania, Australia.
Website: www.spatialdbadvisor.com
Email: simon at spatialdbadvisor.com
Voice: +613 9016 3910
Mobile: +61 418 396391
Skype: sggreener
Longitude: 147.20515 (147° 12' 18" E)
Latitude: -43.01530 (43° 00' 55" S)
NAC:W80CK 7SWP3
More information about the postgis-users
mailing list