* Copyright 2001-2003 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
- * the terms of hte GNU General Public Licence. See the COPYING file.
+ * the terms of the GNU General Public Licence. See the COPYING file.
*
**********************************************************************
* $Log$
+ * Revision 1.45 2004/03/29 10:20:48 strk
+ * Fixed a bug in WKB parsing for Multipoints.
+ * Fixed a bug in -d handling for WKB.
+ * Added point->multipoint fluffing capabilities.
+ *
* Revision 1.44 2004/03/10 18:46:07 strk
* Fixed a bug reducing the output shapes from Multipolygon tables.
*
DBFHandle dbf;
SHPHandle shp;
int geotype;
+int outshptype;
int is3d;
int binary;
#ifdef USE_WKB
int reverse_points(int num_points,double *x,double *y,double *z);
int is_clockwise(int num_points,double *x,double *y,double *z);
int is_bigendian(void);
+SHPObject * shape_creator_wrapper(char *str, int idx, SHPHandle shp, int is3d);
+SHPObject * shape_creator_wrapper_WKB(byte *str, int idx);
/* WKB functions */
SHPObject * create_polygon3D_WKB(byte *wkb, int shape_id);
void skipbyte(byte **c);
byte popbyte(byte **c);
uint32 popint(byte **c);
+uint32 getint(byte *c);
void skipint(byte **c);
double popdouble(byte **c);
void skipdouble(byte **c);
+SHPObject *
+shape_creator_wrapper_WKB(byte *str, int idx)
+{
+ byte *ptr = str;
+ uint32 type;
+ int is3d;
+
+ // skip byte order
+ skipbyte(&ptr);
+
+ // get type
+ type = getint(ptr);
+
+ is3d = type&WKB3DOFFSET;
+
+ switch(type)
+ {
+ case MULTILINETYPE:
+ if ( is3d )
+ return create_multiline3D_WKB(str, idx);
+ else
+ return create_multiline2D_WKB(str, idx);
+
+ case LINETYPE:
+ if ( is3d )
+ return create_line3D_WKB(str, idx);
+ else
+ return create_line2D_WKB(str, idx);
+ case POLYGONTYPE:
+ if ( is3d )
+ return create_polygon3D_WKB(str, idx);
+ else
+ return create_polygon2D_WKB(str, idx);
+ case MULTIPOLYGONTYPE:
+ if ( is3d )
+ return create_multipolygon3D_WKB(str, idx);
+ else
+ return create_multipolygon2D_WKB(str, idx);
+
+ case POINTTYPE:
+ if ( is3d )
+ return create_point3D_WKB(str, idx);
+ else
+ return create_point2D_WKB(str, idx);
+
+ case MULTIPOINTTYPE:
+ if ( is3d )
+ return create_multipoint3D_WKB(str, idx);
+ else
+ return create_multipoint2D_WKB(str, idx);
+
+ default:
+ fprintf(stderr, "Unknown WKB type (%lu) - (%s:%d)\n",
+ type, __FILE__, __LINE__);
+ return NULL;
+ }
+}
+
+SHPObject *
+shape_creator_wrapper(char *str, int idx, SHPHandle shp, int is3d)
+{
+ char *ptr;
+
+ ptr = strchr(str,';');
+ ptr++;
+ if ( (ptr == NULL) || (*ptr == 0) ){
+ fprintf(stderr, "Malformed WKT\n");
+ return NULL;
+ }
+
+ if ( ! strncmp(ptr, "MULTILIN", 8) )
+ return create_multilines(str, idx, shp, is3d);
+ if ( ! strncmp(ptr, "MULTIPOL", 8) )
+ return create_multipolygons(str, idx, shp, is3d);
+ if ( ! strncmp(ptr, "MULTIPOI", 8) )
+ return create_multipoints(str, idx, shp, is3d);
+ if ( ! strncmp(ptr, "LINESTRI", 8) )
+ return create_lines(str, idx, shp, is3d);
+ if ( ! strncmp(ptr, "POLYGON", 7) )
+ return create_polygons(str, idx, shp, is3d);
+ if ( ! strncmp(ptr, "POINT", 5) )
+ return create_points(str, idx, shp, is3d);
+
+ fprintf(stderr, "Unknown geometry type provided (%s)\n", ptr);
+ return NULL;
+
+}
+
//reads points into x,y,z co-ord arrays
y = popdouble(&wkb);
z = popdouble(&wkb);
- obj = SHPCreateSimpleObject(SHPT_POINTZ,1,&x,&y,&z);
+ if ( geotype == POINTTYPE )
+ {
+ obj = SHPCreateSimpleObject(SHPT_POINTZ,1,&x,&y,&z);
+ }
+ else if ( geotype == MULTIPOINTTYPE )
+ {
+ //fprintf(stderr, "create_point3D_WKB: fluffing to MULTIPOINT\n");
+ obj = SHPCreateSimpleObject(SHPT_MULTIPOINTZ, 1, &x, &y, &z);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: create_point2D_WKB called with wrong geometry type (%d)\n", geotype);
+ return NULL;
+ }
return obj;
}
x = popdouble(&wkb);
y = popdouble(&wkb);
- obj = SHPCreateSimpleObject(SHPT_POINT, 1, &x, &y, NULL);
+ obj = SHPCreateSimpleObject(outshptype, 1, &x, &y, NULL);
return obj;
}
SHPObject *
-create_points(char *str, int shape_id, SHPHandle shp, int dims)
+create_points(char *str, int shape_id, SHPHandle shp, int is3d)
{
double *x,
*z;
SHPObject *obj;
int notnull;
+ int outtype;
+
notnull = 1;
x = (double *)malloc(sizeof(double));
z = (double *)malloc(sizeof(double));
notnull = parse_points(str,1,x,y,z);
-
- if(dims == 0){
- if(notnull > 0){
- obj = SHPCreateSimpleObject(SHPT_POINT,1,x,y,z);
- }else{
- obj = SHPCreateSimpleObject(SHPT_NULL,1,x,y,z);
- }
- }else{
- if(notnull > 0){
- obj = SHPCreateSimpleObject(SHPT_POINTZ,1,x,y,z);
- }else{
- obj = SHPCreateSimpleObject(SHPT_NULL,1,x,y,z);
- }
+
+ if ( ! notnull )
+ {
+ outtype = SHPT_NULL;
}
+ else if ( geotype == POINTTYPE )
+ {
+ outtype = is3d ? SHPT_POINTZ : SHPT_POINT;
+ }
+ else if ( geotype == MULTIPOINTTYPE )
+ {
+ //fprintf(stderr, "create_points: fluffing to MULTIPOINT\n");
+ outtype = is3d ? SHPT_MULTIPOINTZ : SHPT_MULTIPOINT;
+ }
+ else
+ {
+ fprintf(stderr, "create_points called with wrong geometry type (%d)\n", geotype);
+ return NULL;
+ }
+
+ obj = SHPCreateSimpleObject(outtype,1,x,y,z);
free(x); free(y); free(z);
return obj;
z[pn]=popdouble(&wkb);
}
- obj = SHPCreateSimpleObject(SHPT_MULTIPOINTZ,1,x,y,z);
+ obj = SHPCreateSimpleObject(SHPT_MULTIPOINTZ,npoints,x,y,z);
free(x); free(y); free(z);
return obj;
{
SHPObject *obj;
double *x=NULL, *y=NULL;
- int npoints;
- int pn;
+ uint32 npoints;
+ uint32 pn;
// skip byteOrder and type
skipbyte(&wkb); skipint(&wkb);
for (pn=0; pn<npoints; pn++)
{
+ skipbyte(&wkb); // byteOrder
+ skipint(&wkb); // wkbType
x[pn]=popdouble(&wkb);
y[pn]=popdouble(&wkb);
}
- obj = SHPCreateSimpleObject(SHPT_MULTIPOINT,1,x,y,NULL);
+ obj = SHPCreateSimpleObject(outshptype,npoints,x,y,NULL);
free(x); free(y);
return obj;
totpoints += npoints;
}
- obj = SHPCreateObject(SHPT_POLYGON, shape_id, nrings,
+ obj = SHPCreateObject(outshptype, shape_id, nrings,
part_index, NULL, totpoints,
x, y, z, NULL);
printf("End of polygons\n");
#endif
- obj = SHPCreateObject(SHPT_POLYGON, shape_id, nparts,
+ obj = SHPCreateObject(outshptype, shape_id, nparts,
part_index, NULL, totpoints,
x, y, NULL, NULL);
#endif
#ifdef USE_WKB
- obj = shape_creator(val, row);
+ obj = shape_creator_wrapper_WKB(val, row);
+ //obj = shape_creator(val, row);
#else
- obj = shape_creator(val, row, shp, is3d);
+ obj = shape_creator_wrapper(val, row, shp, is3d);
+ //obj = shape_creator(val, row, shp, is3d);
#endif
if ( ! obj )
{
char query[1024];
PGresult *res;
char *geo_str; // the geometry type string
+ int multitype=0;
+ int basetype=0;
+ int foundmulti=0;
+ int foundsingle=0;
+ int i;
//get what kind of Geometry type is in the table
if ( schema )
return -1;
}
- if(PQntuples(res) == 1 ){
- geo_str = (char *)malloc(strlen(PQgetvalue(res, 0, 0))+1);
- memcpy(geo_str, (char *)PQgetvalue(res, 0, 0),strlen(PQgetvalue(res,0,0))+1);
- }else if(PQntuples(res) > 1 ){
- fprintf(stderr, "ERROR: Cannot have multiple geometry types in a shapefile.\nUse option -t(unimplemented currently,sorry...) to specify what type of geometry you want dumped\n\n");
- return -1;
- }else{
- printf("ERROR: Cannot determine geometry type of table.\n");
+ if (PQntuples(res) == 0)
+ {
+ printf("ERROR: Cannot determine geometry type (empty table).\n");
return -1;
}
- if ( ! strncmp(geo_str, "MULTILIN", 8) ) return MULTILINETYPE;
- if ( ! strncmp(geo_str, "MULTIPOL", 8) ) return MULTIPOLYGONTYPE;
- if ( ! strncmp(geo_str, "MULTIPOI", 8) ) return MULTIPOINTTYPE;
- if ( ! strncmp(geo_str, "LINESTRI", 8) ) return LINETYPE;
- if ( ! strncmp(geo_str, "POLYGON", 7) ) return POLYGONTYPE;
- if ( ! strncmp(geo_str, "POINT", 5) ) return POINTTYPE;
+ /* This will iterate max 2 times */
+ for (i=0; i<PQntuples(res); i++)
+ {
+ geo_str = PQgetvalue(res, i, 0);
+ if ( ! strncmp(geo_str, "MULTI", 5) )
+ {
+ foundmulti=1;
+ geo_str+=5;
+ }
+ else
+ {
+ foundsingle=1;
+ }
+
+ if ( ! strncmp(geo_str, "LINESTRI", 8) )
+ {
+ if ( basetype && basetype != LINETYPE )
+ {
+ fprintf(stderr, "ERROR: uncompatible mixed geometries in table\n");
+ return -1;
+ }
+ basetype = LINETYPE;
+ multitype = MULTILINETYPE;
+ }
+ else if ( ! strncmp(geo_str, "POLYGON", 7) )
+ {
+ if ( basetype && basetype != POLYGONTYPE )
+ {
+ fprintf(stderr, "ERROR: uncompatible mixed geometries in table\n");
+ return -1;
+ }
+ basetype = POLYGONTYPE;
+ multitype = MULTIPOLYGONTYPE;
+ }
+ else if ( ! strncmp(geo_str, "POINT", 5) )
+ {
+ if ( basetype && basetype != POINTTYPE )
+ {
+ fprintf(stderr, "ERROR: uncompatible mixed geometries in table\n");
+ return -1;
+ }
+ basetype = POINTTYPE;
+ multitype = MULTIPOINTTYPE;
+ }
+ else
+ {
+ fprintf(stderr, "type '%s' is not Supported at this time.\n",
+ geo_str);
+ fprintf(stderr, "The DBF file will be created but not the shx "
+ "or shp files.\n");
+ return 0;
+ }
+ }
+
+ if ( foundmulti )
+ return multitype;
+ else
+ return basetype;
- fprintf(stderr, "type '%s' is not Supported at this time.\n",
- geo_str);
- fprintf(stderr, "The DBF file will be created but not the shx "
- "or shp files.\n");
- return 0;
}
void
sprintf(query, "SELECT a.attname, a.atttypid, a.attlen FROM "
"pg_attribute a, pg_class c, pg_namespace n WHERE "
"n.nspname = '%s' AND a.attrelid = c.oid AND "
+ "a.atttypid != 0 AND "
"a.attnum > 0 AND c.relname = '%s'", schema, table);
}
else
sprintf(query, "SELECT a.attname, a.atttypid, a.attlen FROM "
"pg_attribute a, pg_class c WHERE "
"a.attrelid = c.oid and a.attnum > 0 AND "
+ "a.atttypid != 0 AND "
"c.relname = '%s'", table);
}
switch (geotype)
{
case MULTILINETYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_ARCZ);
-#ifdef USE_WKB
- shape_creator = create_multiline3D_WKB;
-#else
- shape_creator = create_multilines;
-#endif
- }
- else
- {
- shp = SHPCreate(shp_file, SHPT_ARC);
-#ifdef USE_WKB
- shape_creator = create_multiline2D_WKB;
-#else
- shape_creator = create_multilines;
-#endif
- }
- break;
-
case LINETYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_ARCZ);
-#ifdef USE_WKB
- shape_creator = create_line3D_WKB;
-#else
- shape_creator = create_lines;
-#endif
- }
- else
- {
- shp = SHPCreate(shp_file, SHPT_ARC);
-#ifdef USE_WKB
- shape_creator = create_line2D_WKB;
-#else
- shape_creator = create_lines;
-#endif
- }
-
+ if ( is3d ) outshptype=SHPT_ARCZ;
+ else outshptype=SHPT_ARC;
break;
-
+
case POLYGONTYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_POLYGONZ);
-#ifdef USE_WKB
- shape_creator = create_polygon3D_WKB;
-#else
- shape_creator = create_polygons;
-#endif
- }
- else
- {
- shp = SHPCreate(shp_file, SHPT_POLYGON);
-#ifdef USE_WKB
- shape_creator = create_polygon2D_WKB;
-#else
- shape_creator = create_polygons;
-#endif
- }
- break;
-
case MULTIPOLYGONTYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_POLYGONZ);
-#ifdef USE_WKB
- shape_creator = create_multipolygon3D_WKB;
-#else
- shape_creator = create_multipolygons;
-#endif
- }
- else
- {
-#ifdef USE_WKB
- shape_creator = create_multipolygon2D_WKB;
-#else
- shape_creator = create_multipolygons;
-#endif
- shp = SHPCreate(shp_file, SHPT_POLYGON);
- }
+ if ( is3d ) outshptype=SHPT_POLYGONZ;
+ else outshptype=SHPT_POLYGON;
break;
case POINTTYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_POINTZ);
-#ifdef USE_WKB
- shape_creator = create_point3D_WKB;
-#else
- shape_creator = create_points;
-#endif
- }
- else
- {
- shp = SHPCreate(shp_file, SHPT_POINT);
-#ifdef USE_WKB
- shape_creator = create_point2D_WKB;
-#else
- shape_creator = create_points;
-#endif
- }
+ if ( is3d ) outshptype=SHPT_POINTZ;
+ else outshptype=SHPT_POINT;
break;
case MULTIPOINTTYPE:
- if ( is3d )
- {
- shp = SHPCreate(shp_file, SHPT_MULTIPOINTZ);
-#ifdef USE_WKB
- shape_creator = create_multipoint3D_WKB;
-#else
- shape_creator = create_multipoints;
-#endif
- }
- else
- {
-#ifdef USE_WKB
- shape_creator = create_multipoint2D_WKB;
-#else
- shape_creator = create_multipoints;
-#endif
- shp = SHPCreate(shp_file, SHPT_MULTIPOINT);
- }
+ if ( is3d ) outshptype=SHPT_MULTIPOINTZ;
+ else outshptype=SHPT_MULTIPOINT;
break;
return 0;
}
+ shp = SHPCreate(shp_file, outshptype);
}
/*
}
else
{
- sprintf(buf, "\"%s\"::text", mainscan_flds[i]);
+ if ( binary )
+ sprintf(buf, "\"%s\"::text", mainscan_flds[i]);
+ else
+ sprintf(buf, "\"%s\"", mainscan_flds[i]);
}
strcat(main_scan_query, buf);
return i;
}
+uint32 getint(byte *c) {
+ uint32 i;
+ memcpy(&i, c, 4);
+ return i;
+}
+
void skipint(byte **c) {
*c+=4;
}