[postgis-users] Create POLYGON from Several LINESTRINGs

Avery Penniston apenniston at geo-comm.com
Tue Jun 22 14:39:56 PDT 2010


I believe I have figured out what the problem was.  It seems that
through the process of creating the CIRCULARSTRING and then converting
it to a LINESTRING using st_curvetoline the value of the endpoints of
the curve are not quite the same as endpoints of the chords upon which
it is based.  

 

Whether this is due to a precision loss when getting the the x/y
coordinate values as input for the CIRCULARSTRING, or whether it is a
floating point precision problem when comparing the points I don't know,
but I do have a solution for anyone who is interested: Simply replace
the end points of the CIRCULARSTRING after converting it to a LINESTRING
with the known 'good' endpoints from the chords.  The updated function
below should reflect the changes.  

 

Thanks for the help Eric, it gave me part of the solution and got me
thinking in the right direction to get the rest of it.

 

 

CREATE OR REPLACE FUNCTION wedgefunc(outerradius float, startangle
float, openingangle float)

  RETURNS text AS

$BODY$

  DECLARE

    startchord geometry;

    midchord geometry;

    endchord geometry;

    revstartchord geometry;

    outerarc text;

    outerarcline geometry;

    poly geometry;

 

  BEGIN

  -- Rotate a horizontal line to form chords - the 'mid' chord is to
help form the CIRCULARLINESTRING

                startchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle)
;

                midchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle
+ (.5 * openingangle));

                endchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle
+  openingangle);

                

  --Make a reversal of the start chord - not sure if this is needed,
just incase the points need to be in order when putting together the
poly

                revstartchord := st_reverse(startchord); 

                

  --Create an arc line by passing the endpoints of the endchord,
midchord, and startchord

                outerarc :=
'CIRCULARSTRING('||st_x(st_endpoint(endchord))||'
'||st_y(st_endpoint(endchord))||','||st_x(st_endpoint(midchord))||'
'||st_y(st_endpoint(midchord))||','||st_x(st_endpoint(startchord))||'
'||st_y(st_endpoint(startchord))||')';

                outerarcline := st_curvetoline(outerarc);

                

  --Replace the start/end points in the arc LINESTRING with points from
the chords to ensure the ring is closed

                outerarcline :=
st_setpoint(outerarcline,0,st_endpoint(endchord));

                outerarcline :=
st_setpoint(outerarcline,st_numpoints(outerarcline)-1,st_startpoint(revs
tartchord));

                

  --Create the polygon by combining the individual LINESTRINGS

                poly := st_buildarea(st_collect(geom))

                FROM (select revstartchord as geom

                                union select endchord as geom

                                union select outerarcline as geom

                ) as u;

 

                return st_astext(poly);

 

  END;

 

  $BODY$

  LANGUAGE 'plpgsql' IMMUTABLE;

 

 

From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net] On Behalf Of
Avery Penniston
Sent: Tuesday, June 22, 2010 3:00 PM
To: PostGIS Users Discussion
Subject: Re: [postgis-users] Create POLYGON from Several LINESTRINGs

 

Thanks for the reply.

 

I tried to use the st_buildarea with st_collect as you suggested by
modifying my wedgefunc function that I posted earlier.  However, now I
don't get anything out of the function.  I believe the collect is
returning a MULTILINESTRING with the three elements to my wedge in it,
but for some reason the st_buildarea function is returning nothing.  Any
ideas?

 

Here is my modified wedgefunc function:

 

CREATE OR REPLACE FUNCTION wedgefunc(outerradius float, startangle
float, openingangle float)

  RETURNS text AS

$BODY$

  DECLARE

    startchord geometry;

    midchord geometry;

    endchord geometry;

    revstartchord geometry;

    outerarc text;

    outerarcline geometry;

    polyborder geometry;

    poly geometry;

 

  BEGIN

  -- Rotate a horizontal line to form chords - the 'mid' chord is to
help form the CIRCULARLINESTRING

                startchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle)
;

                midchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle
+ (.5 * openingangle));

                endchord :=
st_rotate(st_makeline(st_point(0,0),st_point(outerradius,0)),startangle
+  openingangle);

                

  --Make a reversal of the start chord - not sure if this is needed,
just incase the points need to be in order when putting together the
poly

                revstartchord := st_reverse(startchord); 

                

  --Create an arc line by passing the endpoints of the endchord,
midchord, and startchord

                outerarc :=
'CIRCULARSTRING('||st_x(st_endpoint(endchord))||'
'||st_y(st_endpoint(endchord))||','||st_x(st_endpoint(midchord))||'
'||st_y(st_endpoint(midchord))||','||st_x(st_endpoint(startchord))||'
'||st_y(st_endpoint(startchord))||')';

                outerarcline := st_curvetoline(outerarc);

 

  --TRYING ST_BUILDAREA WITH ST_COLLECT AFTER UNIONING THE 3 LINESTRINGS

                poly := st_buildarea(st_collect(geom))

                FROM (select revstartchord as geom

                                union select endchord as geom

                                union select outerarcline as geom

                ) as u;

                return st_astext(poly);

 

  END;

 

  $BODY$

  LANGUAGE 'plpgsql' IMMUTABLE;

 

From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net] On Behalf Of
Randall, Eric
Sent: Tuesday, June 22, 2010 2:26 PM
To: PostGIS Users Discussion
Subject: Re: [postgis-users] Create POLYGON from Several LINESTRINGs

 

 

I think perhaps st_buildarea and st_collect might be what you want.
Below is what I used to create a hexagon out of points->lines which was
then translated (using generate_series) across X and Y to create a
hexagonal grid for the County.   There's probably a simpler way to make
a hexagon but it illustrates the st_buildarea.  Maybe that helps.

 

-Eric 

 

 

 

 

--let's make a hexagon with 1000 foot sides and position it with it's 
--center at 1210000, 610000 (the lower left of the pamap tile extent for
Erie County)
--and create a table 

 

drop table if exists hex1000;
create table hex1000 as
select translate(st_buildarea(st_collect(geom)),1210000, 610000) as geom
from 
(select makeline(st_endpoint(makeline(makepoint(0, 0),makepoint(0, -
1000))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(300)))) as geom 
union select makeline(st_endpoint(rotate(makeline(makepoint(0,
0),makepoint(0, -1000)),
radians(300))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(240))))  as geom 
union select makeline(st_endpoint(rotate(makeline(makepoint(0,
0),makepoint(0, -1000)),
radians(240))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(180))))  as geom 
union select makeline(st_endpoint(rotate(makeline(makepoint(0,
0),makepoint(0, -1000)),
radians(180))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(120))))  as geom 
union select makeline(st_endpoint(rotate(makeline(makepoint(0,
0),makepoint(0, -1000)),
radians(120))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(60))))  as geom 
union select makeline(st_endpoint(rotate(makeline(makepoint(0,
0),makepoint(0, -1000)),
radians(60))),st_endpoint(rotate(makeline(makepoint(0, 0),makepoint(0,
-1000)), radians(0))))  as geom 
) as t1;

 

 

 

 

 

-----Original Message-----
From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net]On Behalf Of Avery
Penniston
Sent: Tuesday, June 22, 2010 2:38 PM
To: postgis-users at postgis.refractions.net
Subject: Re: [postgis-users] Create POLYGON from Several LINESTRINGs

	I'm trying to create 'pie wedge' shaped polygons by building
them in a Postgres function.  I am able to create the 2 straight chords
and the arc as separate LINESTRINGs, and I have verified that each
LINESTRING shares its endpoints with the other two LINESTRINGs.
However, I am having trouble putting the individual parts together to
form a POLYGON.

	 

	I tried to ST_UNION the 3 LINESTRINGs together, and the result
is a MULTILINESTRING.  I then call ST_LINEMERGE to convert the
MULTILINESTRING to a single LINESTRING so I can pass it to the
ST_POLYGON function, but the result of the ST_LINEMERGE is a
MULTILINESTRING.  

	 

	I tried using ST_COLLECT instead of ST_UNION, but then I got a
GEOMETRYCOLLECTION containing a MULTILINESTRING and a LINESTRING.

	 

	Does anybody have some advice for creating a POLYGON from 3 or
more separate LINESTRINGs?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20100622/3275c775/attachment.html>


More information about the postgis-users mailing list