You're right about how the current PostGIS union works.

The CascadedUnion algorithm in JTS uses spatial indexing and some other heuristics to obtain very fast performance.

The Java2D approach that you give is similar to the buffer(0) trick that was the recommended way to do fast unioning prior to CascadedUnion. buffer(0) is sometime less stable, however, and it doesn't handle non-polygonal geometry.

Bresnahan, Mike wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

FWIW:  The unioning operations currently in PostGIS are very
inefficient.

Do I guess right that PostGIS iterates over each geometry and unions it
with the result of all previous geometries, something like this:

            java.awt.geom.Area area = null;
            for (Geometry geom : geomList) {
                if (area == null) {
                    area = ConvertToArea(geom);
                }
                else {
                    path = area.add(ConvertToArea(geom)); // union
                }
            }

AFAIK, that is what Oracle does and it is quite slow.

We are working on improving the union operation in PostGIS and
hopefully
will have at least a first draft to show in the next release.  Most
notably
porting the JTS logic for doing Cascaded Unions to PostGIS.

By Cascaded Unions do you mean a routine that works something like this:

java.awt.geom.Area subArea = null; int rowCount = 0;
            while (result.next()) {
                JGeometry geom = JGeometry.load(result.getBytes(1));
                java.awt.Shape shape =
Java2DClipper.geometryToShape(geom);
                if (shape != null) {
                    if (subArea == null) {
                        subArea = new java.awt.geom.Area(shape);
                    }
                    else {
                        subArea.add(new java.awt.geom.Area(shape));
                    }
                    ++rowCount;
                    if (rowCount % 10 == 0) {
                         if (area == null) {
                            area = subArea;
                        }
                        else {
                            area.add(subArea);
                        }
                        subArea = null;
                    }
                }
                System.out.println(rowCount);
            }

I have found that this is indeed faster that the first approach, but
what I have found that is even faster is to create one large geometry
collection and union it with itself like this:

            java.awt.geom.GeneralPath path = null;
            for (Geometry geom : geomList) {
                if (path == null) {
                    path = ConvertToPath(geom);
                }
                else {
                    path = AppendToPath(path, geom);
                }
            }
            java.awt.geom.Area area = new java.awt.geom.Area(path);
            area.add(area); // self-union

I think the gain here is that you only build the temp data structures
for each polygon once. I'm guessing that this is what ArcMap does.

-----BEGIN PGP SIGNATURE-----
Version: PGP Universal 2.8.3
Charset: us-ascii

wsBVAwUBSKTDPR6WPRoYuvd0AQjlRwf/Rci7f0R8jm/deW5Q7kA1tBwXRFSdd3S9
dQwp/Sl/5wTcQc/NbV8kRM5MHeDRPzL2XBUY7zp/ypdLYv5RDi0+niJSmLWiYg5T
vu4ot5Z4de1PjWncSmHNQqqVcNrxy4oxwLtrULgEZ3yMPcW3ffxwHFZzxNBULNCi
VjWISI670HOb/7vmzjgsWrBgPgXl5gMRsDp6eiR+L+SDBBqZJTwHaR6WV86hGsYw
t92QkvKUYNq0DOSmcjnNgIE2xxDuCAABed5ZwLiCF34hP3bN5nnfOs29Fd+yTP/V
pEKxZYrPn/v6RNUNPuw9MhjGEvGA4YkcL6y/Bbf1nnvaK0EseOzwow==
=Y1Pu
-----END PGP SIGNATURE-----
_______________________________________________
postgis-users mailing list
postgis-users@postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users


--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

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

Reply via email to