views:

102

answers:

2
SELECT id, ST_Box2D(areas) AS bbox FROM mytable;

In this example, the table "mytable" contains two columns: "id" is the unique id number of the row and "areas" is a geometry field containing one MULTIPOLYGON per row.


This works fine for multipolygons containing only one polygon, but some rows have polygons very spread apart, hence the bounding box is not relevant when the multipolygon contains one polygon in Europe and one in Canada for example.

So I would need a way to get one box2d per polygon per multipolygon, but I haven't found how just yet. More exactly, my goal is to return one multipolygon per row, containing one box2d per polygon.


First example

  • id: 123
  • area: a multipolygon containing only one oval polygon in Australia
  • therefore bbox should return a multipolygon containing only one rectangle (the bounding box) in Australia

Second example

  • id: 321
  • area: a multipolygon containing one circle in Paris, one circle in Toronto
  • therefore bbox should return a multipolygon containing one rectangle in Paris, one rectangle in Toronto
+1  A: 

You would have to box the relevant bits (say the Canadian and French components) separately. The best tool for this in PostGIS is the geometry accessor ST_GeometryN(geometry,int) (reference: http://postgis.refractions.net/docs/ST_GeometryN.html ). That link has a good example of combining the accessor with ST_NumGeometries.

UPDATE PER COMMENT:

Here is a simple example from San Francisco -- this table contains a geometry field called the_geom, gid record 1 is a field with two multipolygons as reported by st_numgeometries (note the ordinal is indexed at 1 not 0):

=> select st_box2d(st_geometryn(the_geom, 1)) from tl_2009_06075_cousub00 \
 where gid = 1;

                                st_box2d                                 
-------------------------------------------------------------------------
 BOX(-123.173828125 37.6398277282715,-122.935707092285 37.8230590820312)
(1 row)

=> select st_box2d(st_geometryn(the_geom, 2)) from tl_2009_06075_cousub00 \
 where gid = 1;

                                  st_box2d                                  
----------------------------------------------------------------------------
 BOX(-122.612289428711 37.7067184448242,-122.281776428223 37.9298248291016)
(1 row)
bvmou
Well I have tried this earlier as well:SELECT numgeometries(areas) AS count, geometryn(areas, generate_series(1, numgeometries(areas))) AS bbox FROM mytable;However I don't know where I could insert the st_box2d instruction within the statement, nor how to agglomerate them per row (st_collect would be my first idea, but it's tricky) and wasn't sure if I'm going in the right direction at all.
wildpeaks
+2  A: 

Hallo

You should use ST_Dump (http://postgis.org/documentation/manual-1.5/ST_Dump.html)

Then you will get one row per polygon. The other fields will be duplicated when the geometry is split. It is like an aggregate function but the other way.

The syntax gets a little special since it outputs a compound data type so you have to extract the geometry part like this:

SELECT (ST_Dump(the_geom)).geom from mytable.

since this gives you more rows in the table you should just make a new table from the query.

then you can just create an index on that new geometry column in the new table and it will be built on bounding boxes for each single polygon.

HTH

/Nicklas

Do you want your polygons too at one row each? That is what I thought, but if you want only a table with bboxes, one per row with an id references the original multipolygon (you will of cource get the same id repeated for every part of the multipolygon) then you can do the same byt just extracting the bboxes something like:

Create table newTable as SELECT ID, BOX2D((ST_Dump(the_geom)).geom) as myBox from originamTable

I am afraid I don't really get what you want, but you have a lot of possibilities with ST_Dump in cases like this.

Nicklas Avén
(ST_Dump()).geom is exactly what I needed (and I'm sure I wouldn't have found it in a million years). Thanks :)
wildpeaks