[postgis-users] shp2pgsql Non-MULTI patch
Markus Schaber
schabi at logix-tt.com
Thu Oct 5 03:10:58 PDT 2006
Hi,
Markus Schaber wrote:
> I attached a small and untested patch to add an -S option to shp2pgsql
> which makes LINESTRINGS and POLYGONS instead of the MULTI* geometries,
> and enforces this restriction.
Here's an updated patch that also corrects table creation, and the man page.
Please test.
If I don't hear any complaints the next days, I'll commit :-)
Markus
--
Markus Schaber | Logical Tracking&Tracing International AG
Dipl. Inf. | Software Development GIS
Fight against software patents in Europe! www.ffii.org
www.nosoftwarepatents.org
-------------- next part --------------
Index: doc/man/shp2pgsql.1
===================================================================
--- doc/man/shp2pgsql.1 (revision 2497)
+++ doc/man/shp2pgsql.1 (working copy)
@@ -52,6 +52,13 @@
Coerce all integers to standard 32\-bit integers, do not create 64\-bit bigints, even if the DBF header signature appears to warrant it.
.TP
+\fB\-S\fR
+Generate simple Geometries instead of MULTIgeometries. Shape files don't differ between LINESTRINGs
+and MULTILINESTRINGs, so shp2pgsql generates MULTILINESTRINGs by default. This switch will produce
+LINESTRINGs instead, but shp2pgsql will fail when it hits a real MULTILINESTRING. The same works
+for POLYGONs vs. MULTIPOLYGONs.
+
+.TP
\fB\-w\fR
Output WKT format, for use with older (0.x) versions of PostGIS.
Note that this will introduce coordinate drifts and will drop
Index: loader/shp2pgsql.c
===================================================================
--- loader/shp2pgsql.c (revision 2497)
+++ loader/shp2pgsql.c (working copy)
@@ -69,6 +69,7 @@
/* globals */
int dump_format = 0; /* 0=insert statements, 1 = dump */
+int simple_geometries = 0; /* 0 = MULTILINESTRING/MULTIPOLYGON, 1 = LINESTRING/POLYGON */
int quoteidentifiers = 0;
int forceint4 = 0;
int createindex = 0;
@@ -759,6 +760,8 @@
fprintf(stderr, "\n");
fprintf(stderr, " -I Create a GiST index on the geometry column.\n");
fprintf(stderr, "\n");
+ fprintf(stderr, " -S Generate simple geometries instead of MULTI geometries.\n");
+ fprintf(stderr, "\n");
fprintf(stderr, " -w Use wkt format (for postgis-0.x support - drops M - drifts coordinates).\n");
#ifdef USE_ICONV
fprintf(stderr, "\n");
@@ -792,9 +795,17 @@
if (!dump_format) printf("'");
if ( sr_id && sr_id != "-1" ) printf("SRID=%s;", sr_id);
- print_wkb_byte(getEndianByte());
- print_wkb_int(wkbtype);
- print_wkb_int(obj->nParts);
+ if (simple_geometries==0) // We write MULTI geometries, so generate Header
+ {
+ print_wkb_byte(getEndianByte());
+ print_wkb_int(wkbtype);
+ print_wkb_int(obj->nParts); /* npolys */
+ }
+ else if ((obj->nParts)!=1) // We write Non-MULTI geometries, but have several parts:
+ {
+ fprintf(stderr, "We have a MultiLineString with %d parts, can't use -S switch!\n", obj->nParts);
+ exit(1);
+ }
for (pi=0; pi<obj->nParts; pi++)
{
@@ -845,6 +856,22 @@
if (dump_format) printf("SRID=%s;MULTILINESTRING(",sr_id);
else printf("GeometryFromText('MULTILINESTRING (");
+
+ if (dump_format) printf("SRID=%s;",sr_id );
+ else printf("GeometryFromText('");
+
+ if (simple_geometries==0) // We write MULTI geometries, so generate Header
+ {
+ printf("MULTILINESTRING(");
+ } else if ((obj->nParts)==1)
+ {
+ printf("POLYGON");
+ }
+ else // We write Non-MULTI geometries, but have several parts:
+ {
+ fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", obj->nParts);
+ exit(1);
+ }
for (pi=0; pi<obj->nParts; pi++)
{
@@ -874,8 +901,10 @@
}
- if (dump_format) printf(")\n");
- else printf(")',%s) );\n",sr_id);
+ if (simple_geometries==0) printf(")");
+
+ if (dump_format) printf("\n");
+ else printf("',%s) );\n",sr_id);
}
int
@@ -1051,9 +1080,17 @@
if (!dump_format) printf("'");
if ( sr_id && sr_id != "-1" ) printf("SRID=%s;", sr_id);
- print_wkb_byte(getEndianByte());
- print_wkb_int(wkbtype);
- print_wkb_int(out_index); /* npolys */
+ if (simple_geometries==0) // We write MULTI geometries, so generate Header
+ {
+ print_wkb_byte(getEndianByte());
+ print_wkb_int(wkbtype);
+ print_wkb_int(out_index); /* npolys */
+ }
+ else if (out_index!=1) // We write Non-MULTI geometries, but have several parts:
+ {
+ fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", out_index);
+ exit(1);
+ }
/* Write the coordinates */
for(pi=0; pi<out_index; pi++)
@@ -1112,8 +1149,22 @@
out_index = FindPolygons(obj, &Outer);
- if (dump_format) printf("SRID=%s;MULTIPOLYGON(",sr_id );
- else printf("GeometryFromText('MULTIPOLYGON(");
+ if (dump_format) printf("SRID=%s;",sr_id );
+ else printf("GeometryFromText('");
+
+ if (simple_geometries==0) // We write MULTI geometries, so generate Header
+ {
+ printf("MULTIPOLYGON(");
+ }
+ else if (out_index==1)
+ {
+ printf("POLYGON");
+ }
+ else
+ { // We write Non-MULTI geometries, but have several parts:
+ fprintf(stderr, "We have a Multipolygon with %d parts, can't use -S switch!\n", out_index);
+ exit(1);
+ }
/* Write the coordinates */
for(pi=0; pi<out_index; pi++)
@@ -1149,8 +1200,10 @@
}
- if (dump_format) printf(")\n");
- else printf(")',%s) );\n",sr_id);
+ if (simple_geometries==0) printf(")");
+
+ if (dump_format) printf("\n");
+ else printf("',%s) );\n",sr_id);
/* Release all memory */
ReleasePolygons(Outer, out_index);
@@ -1228,7 +1281,7 @@
extern char *optarg;
extern int optind;
- while ((c = getopt(ARGC, ARGV, "kcdapDs:g:iW:wIN:")) != EOF){
+ while ((c = getopt(ARGC, ARGV, "kcdapDs:Sg:iW:wIN:")) != EOF){
switch (c) {
case 'c':
if (opt == ' ')
@@ -1257,6 +1310,9 @@
case 'D':
dump_format =1;
break;
+ case 'S':
+ simple_geometries =1;
+ break;
case 's':
sr_id = optarg;
break;
@@ -1449,6 +1505,13 @@
shpfiletype);
break;
}
+
+ if (simple_geometries)
+ {
+ // adjust geometry name for CREATE TABLE by skipping MULTI
+ if ((wkbtype & 0x7) == MULTIPOLYGONTYPE) pgtype += 5;
+ if ((wkbtype & 0x7) == MULTILINETYPE) pgtype += 5;
+ }
}
char *