2001-09-19 18:47:32 +00:00
//compile line for Refractions' Solaris machine...
//gcc -g -I/data3/postgresql-7.1.2/include -L/data3/postgresql-7.1.2/lib dump.c ../shapelib-1.2.8/shpopen.o ../shapelib-1.2.8/dbfopen.o -o dump -lpq
2001-10-11 18:07:33 +00:00
# include <getopt.h>
2001-09-19 18:47:32 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <math.h>
# include "libpq-fe.h"
# include "shapefil.h"
static void exit_nicely ( PGconn * conn ) {
PQfinish ( conn ) ;
exit ( 1 ) ;
}
2001-10-04 18:53:33 +00:00
int create_lines ( char * str , int shape_id , SHPHandle shp , int dims ) ;
int create_multilines ( char * str , int shape_id , SHPHandle shp , int dims ) ;
int create_points ( char * str , SHPHandle shp , int dims ) ;
int create_multipoints ( char * str , SHPHandle shp , int dims ) ;
int create_polygons ( char * str , int shape_id , SHPHandle shp , int dims ) ;
int create_multipolygons ( char * str , int shape_id , SHPHandle shp , int dims ) ;
2001-09-20 18:14:43 +00:00
int parse_points ( char * str , int num_points , double * x , double * y , double * z ) ;
int num_points ( char * str ) ;
int num_lines ( char * str ) ;
char * scan_to_same_level ( char * str ) ;
int points_per_sublist ( char * str , int * npoints , long max_lists ) ;
2001-09-19 18:47:32 +00:00
//main
//usage: dump <database> <table_name> <shape_file_name to create> ["2d" || 3d"]
//database: name of the database on local host
//table_name: which table to dump
//shape_file_name: name of shape file which info is dumped into
//2d or 3d specifies what type of shape file you want, a 2d one or a 3d one. Defaults to 3d if not specifed.
int main ( int ARGC , char * * ARGV ) {
2001-10-04 18:53:33 +00:00
char * pghost , * pgport , * pgoptions , * dbName , * pgpass ,
* query , * query1 , * geo_str , * geo_str_left ,
* geo_col_name , * geo_OID ,
conn_string [ 512 ] , field_name [ 32 ] , table_OID [ 16 ] ,
* shp_file , * pguser , * table ;
int nFields , is3d , c , errflg , curindex ;
2001-09-19 18:47:32 +00:00
int i , j , type , size , flds ;
int type_ary [ 256 ] ;
int OID , geovalue_field ;
DBFHandle dbf ;
SHPHandle shp ;
PGconn * conn ;
PGresult * res , * res2 , * res3 ;
2001-10-11 18:07:33 +00:00
table = NULL ;
geo_col_name = NULL ;
geo_str = NULL ;
dbName = NULL ;
2001-10-04 18:53:33 +00:00
pghost = NULL ;
shp_file = NULL ;
pgport = NULL ;
2001-10-11 18:07:33 +00:00
geovalue_field = 0 ;
2001-10-04 18:53:33 +00:00
pguser = " " ;
pgpass = " " ;
is3d = 0 ;
2001-10-11 18:07:33 +00:00
errflg = 0 ;
OID = 0 ;
2001-10-04 18:53:33 +00:00
while ( ( c = getopt ( ARGC , ARGV , " f:h:du:p:P: " ) ) ! = EOF ) {
switch ( c ) {
case ' f ' :
shp_file = optarg ;
break ;
case ' h ' :
pghost = optarg ;
break ;
case ' d ' :
is3d = 1 ;
break ;
case ' u ' :
pguser = optarg ;
break ;
case ' p ' :
pgport = optarg ;
break ;
case ' P ' :
pgpass = optarg ;
break ;
case ' ? ' :
errflg = 1 ;
}
}
curindex = 0 ;
for ( ; optind < ARGC ; optind + + ) {
if ( curindex = = 0 ) {
dbName = ARGV [ optind ] ;
} else if ( curindex = = 1 ) {
table = ARGV [ optind ] ;
}
curindex + + ;
}
if ( curindex ! = 2 ) {
errflg = 1 ;
}
if ( errflg = = 1 ) {
printf ( " \n **ERROR** invalid option or command parameters \n " ) ;
printf ( " \n " ) ;
2001-10-11 18:26:51 +00:00
printf ( " USAGE: pgsql2shp [<options>] <database> <table> \n " ) ;
2001-10-04 18:53:33 +00:00
printf ( " \n " ) ;
printf ( " OPTIONS: \n " ) ;
2001-10-11 18:26:51 +00:00
printf ( " -d Set the dump file to 3 dimensions, if this option is not used \n " ) ;
printf ( " all dumping will be 2d only. \n " ) ;
printf ( " -f <filename> Use this option to specify the name of the file \n " ) ;
printf ( " to create. \n " ) ;
printf ( " -h <host> Allows you to specify connection to a database on a \n " ) ;
printf ( " machine other than the localhost. \n " ) ;
printf ( " -p <port> Allows you to specify a database port other than 5432. \n " ) ;
printf ( " -P <password> Connect to the database with the specified password. \n " ) ;
printf ( " -u <user> Connect to the database as the specified user. \n " ) ;
2001-10-04 18:53:33 +00:00
exit ( 2 ) ;
}
if ( shp_file = = NULL ) {
shp_file = malloc ( strlen ( table ) + 1 ) ;
strcpy ( shp_file , table ) ;
}
if ( pgport = = NULL ) {
pgport = " 5432 " ;
}
if ( pghost = = NULL ) {
pghost = " localhost " ;
}
if ( strcmp ( pgpass , " " ) = = 0 & & strcmp ( pguser , " " ) = = 0 ) {
pgoptions = malloc ( 1 ) ;
strcpy ( pgoptions , " " ) ;
} else {
pgoptions = malloc ( strlen ( pguser ) + strlen ( pgpass ) + 20 ) ;
if ( strcmp ( pguser , " " ) ! = 0 ) {
strcpy ( pgoptions , " user= " ) ;
strcat ( pgoptions , pguser ) ;
}
if ( strcmp ( pgpass , " " ) ! = 0 ) {
strcat ( pgoptions , " password= " ) ;
strcat ( pgoptions , pgpass ) ;
}
}
2001-09-19 18:47:32 +00:00
2001-10-04 18:53:33 +00:00
printf ( conn_string ) ;
2001-09-19 18:47:32 +00:00
2001-10-04 18:53:33 +00:00
/* make a connection to the specified database */
2001-09-19 18:47:32 +00:00
sprintf ( conn_string , " host=%s %s port=%s dbname=%s " , pghost , pgoptions , pgport , dbName ) ;
conn = PQconnectdb ( conn_string ) ;
/* check to see that the backend connection was successfully made */
if ( PQstatus ( conn ) = = CONNECTION_BAD )
{
fprintf ( stderr , " Connection to database '%s' failed. \n " , dbName ) ;
fprintf ( stderr , " %s " , PQerrorMessage ( conn ) ) ;
exit_nicely ( conn ) ;
}
# ifdef DEBUG
debug = fopen ( " /tmp/trace.out " , " w " ) ;
PQtrace ( conn , debug ) ;
# endif /* DEBUG */
//------------------------------------------------------------
//Get the OID of the geometry type
query1 = ( char * ) malloc ( strlen ( " select OID, typname from pg_type where typname = 'geometry'; " ) + 2 ) ;
strcpy ( query1 , " select OID, typname from pg_type where typname = 'geometry'; " ) ;
res = PQexec ( conn , query1 ) ;
// printf("OID query result: %s\n",PQresultErrorMessage(res));
free ( query1 ) ;
if ( PQntuples ( res ) > 0 ) {
char * temp_int = ( char * ) PQgetvalue ( res , 0 , 0 ) ;
OID = atoi ( temp_int ) ;
} else {
printf ( " Cannot determine geometry type OID, Data-Dump Failed. " ) ;
exit_nicely ( conn ) ;
}
PQclear ( res ) ;
//------------------------------------------------------------
//Get the table from the DB
2001-10-04 18:53:33 +00:00
query = ( char * ) malloc ( strlen ( table ) + strlen ( " select * from " ) + 2 ) ;
2001-09-19 18:47:32 +00:00
strcpy ( query , " select * from " ) ;
2001-10-04 18:53:33 +00:00
strcat ( query , table ) ;
2001-09-19 18:47:32 +00:00
// printf("%s\n",query);
res = PQexec ( conn , query ) ;
if ( PQntuples ( res ) > 0 ) {
} else {
2001-10-04 18:53:33 +00:00
printf ( " Invalid table: '%s' (check spelling and existance of >0 tuples). \n Data-Dump Failed. " , table ) ;
2001-09-19 18:47:32 +00:00
exit_nicely ( conn ) ;
}
//printf("Select * query result: %s\n",PQresultErrorMessage(res));
free ( query ) ;
//------------------------------------------------------------
//Create the dbf file
2001-10-04 18:53:33 +00:00
dbf = DBFCreate ( shp_file ) ;
2001-09-19 18:47:32 +00:00
if ( dbf = = NULL ) {
printf ( " DBF could not be created - Dump FAILED. " ) ;
exit_nicely ( conn ) ;
}
// add the fields to the DBF
nFields = PQnfields ( res ) ;
flds = 0 ; //keep track of how many fields you have actually created
for ( i = 0 ; i < nFields ; i + + ) {
if ( strlen ( PQfname ( res , i ) ) < 32 ) {
strcpy ( field_name , PQfname ( res , i ) ) ;
} else {
printf ( " field name %s is too long, must be less than 32 characters. \n " , PQfname ( res , i ) ) ;
exit_nicely ( conn ) ;
}
for ( j = 0 ; j < i ; j + + ) { //make sure the fields all have unique names, 10-digit limit on dbf names...
if ( strncmp ( field_name , PQfname ( res , j ) , 10 ) = = 0 ) {
printf ( " \n Warning: Field '%s' has first 10 characters which duplicate a previous field name's. \n Renaming it to be: ' " , field_name ) ;
strncpy ( field_name , field_name , 9 ) ;
field_name [ 9 ] = 0 ;
sprintf ( field_name , " %s%d " , field_name , i ) ;
printf ( " %s' \n \n " , field_name ) ;
}
}
type = PQftype ( res , i ) ;
size = PQfsize ( res , i ) ;
if ( type = = 1082 ) { //date field, which we store as a string so we need more width in the column
size = 10 ;
}
if ( size = = - 1 & & type ! = OID ) { //-1 represents variable size in postgres, this should not occur, but use 32 bytes in case it does
query1 = ( char * ) malloc ( 60 ) ; //hardcoded size for the following query
strcpy ( query1 , " select max(octet_length( " ) ;
strcat ( query1 , PQfname ( res , i ) ) ;
strcat ( query1 , " )) from " ) ;
2001-10-04 18:53:33 +00:00
strcat ( query1 , table ) ;
2001-09-19 18:47:32 +00:00
res2 = PQexec ( conn , query1 ) ;
free ( query1 ) ;
if ( PQntuples ( res2 ) > 0 ) {
char * temp_int = ( char * ) PQgetvalue ( res2 , 0 , 0 ) ;
size = atoi ( temp_int ) ;
} else {
size = 32 ;
}
}
if ( type = = 20 | | type = = 21 | | type = = 22 | | type = = 23 ) {
if ( DBFAddField ( dbf , field_name , FTInteger , 16 , 0 ) = = - 1 ) printf ( " error - Field could not be created. \n " ) ;
type_ary [ i ] = 1 ;
flds + + ;
} else if ( type = = 700 | | type = = 701 ) {
if ( DBFAddField ( dbf , field_name , FTDouble , 32 , 10 ) = = - 1 ) printf ( " error - Field could not be created. \n " ) ;
type_ary [ i ] = 2 ;
flds + + ;
} else if ( type = = OID ) {
type_ary [ i ] = 9 ; //the geometry type field
geovalue_field = i ;
flds + + ;
} else {
if ( DBFAddField ( dbf , field_name , FTString , size , 0 ) = = - 1 ) printf ( " error - Field could not be created. \n " ) ;
type_ary [ i ] = 3 ;
flds + + ;
}
}
/* next, print out the instances */
for ( i = 0 ; i < PQntuples ( res ) ; i + + )
{
2001-10-04 18:53:33 +00:00
if ( i % 50 = = 1 ) {
2001-09-19 18:47:32 +00:00
printf ( " DBF tuple - %d added \n " , i ) ;
}
flds = 0 ;
for ( j = 0 ; j < nFields ; j + + ) {
if ( type_ary [ j ] = = 1 ) {
char * temp_int = ( char * ) PQgetvalue ( res , i , j ) ;
int temp = atoi ( temp_int ) ;
if ( DBFWriteIntegerAttribute ( dbf , i , flds , temp ) = = 0 ) printf ( " error(int) - Record could not be created \n " ) ;
flds + + ;
} else if ( type_ary [ j ] = = 2 ) {
char * temp_dbl = PQgetvalue ( res , i , j ) ;
double temp = atof ( temp_dbl ) ;
if ( DBFWriteDoubleAttribute ( dbf , i , flds , temp ) = = 0 ) printf ( " error(double) - Record could not be created \n " ) ;
flds + + ;
} else if ( type_ary [ j ] = = 9 ) {
//this is the geometry type field, would do all the .shp and .shx stuff here i imagine
} else {
char * temp = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , j ) ) * 8 ) ;
temp = ( char * ) PQgetvalue ( res , i , j ) ;
if ( DBFWriteStringAttribute ( dbf , i , flds , temp ) = = 0 ) printf ( " error(string) - Record could not be created \n " ) ;
flds + + ;
}
}
}
2001-10-04 18:53:33 +00:00
printf ( " DBF tuple - %d added \n " , i - 1 ) ;
2001-09-19 18:47:32 +00:00
DBFClose ( dbf ) ;
//--------------------------------------------------------------------
//Now parse the geo_value (All your base belong to us. For great justice.)
//field into the shx and shp files
2001-10-04 18:53:33 +00:00
query = ( char * ) malloc ( strlen ( " select OID from pg_class where relname = ' ' " ) + strlen ( table ) + 2 ) ;
2001-09-20 18:14:43 +00:00
strcpy ( query , " select OID from pg_class where relname = ' " ) ;
2001-10-04 18:53:33 +00:00
strcat ( query , table ) ;
2001-09-20 18:14:43 +00:00
strcat ( query , " ' " ) ;
res3 = PQexec ( conn , query ) ;
if ( PQntuples ( res3 ) = = 1 ) {
strcpy ( table_OID , ( PQgetvalue ( res3 , 0 , 0 ) ) ) ;
} else if ( PQntuples ( res3 ) = = 0 ) {
printf ( " ERROR:Cannot determine name of geometry column. \n " ) ;
exit_nicely ( conn ) ;
} else {
strcpy ( table_OID , ( PQgetvalue ( res3 , 0 , 0 ) ) ) ;
printf ( " Warning: Multiple geometry columns detected, the program will only dump the first geometry " ) ;
//JL - still need to write in some options to allow choosing a different geom col.
}
//get the name of the geometry column
query = ( char * ) malloc ( strlen ( " select attname from pg_attribute where
attrelid = and atttypid = " )+38);
strcpy ( query , " select attname from pg_attribute where attrelid = " ) ;
strcat ( query , table_OID ) ;
strcat ( query , " and atttypid = " ) ;
geo_OID = ( char * ) malloc ( 34 ) ;
sprintf ( geo_OID , " %i " , OID ) ;
strcat ( query , geo_OID ) ;
res3 = PQexec ( conn , query ) ;
if ( PQntuples ( res3 ) = = 1 ) {
geo_col_name = ( char * ) malloc ( strlen ( PQgetvalue ( res3 , 0 , 0 ) ) + 2 ) ;
geo_col_name = PQgetvalue ( res3 , 0 , 0 ) ;
} else if ( PQntuples ( res3 ) = = 0 ) {
printf ( " ERROR:Cannot determine name of geometry column. \n " ) ;
exit_nicely ( conn ) ;
} else {
geo_col_name = ( char * ) malloc ( strlen ( PQgetvalue ( res3 , 0 , 0 ) ) + 2 ) ;
geo_col_name = PQgetvalue ( res3 , 0 , 0 ) ;
printf ( " Warning: Multiple geometry columns detected, the program will only dump the first geometry " ) ;
}
2001-09-19 18:47:32 +00:00
//get what kind of Geometry type is in the table
2001-10-04 18:53:33 +00:00
query = ( char * ) malloc ( strlen ( table ) + strlen ( " select distinct (geometrytype()) from " ) + 18 ) ;
2001-09-20 18:14:43 +00:00
strcpy ( query , " select distinct (geometrytype( " ) ;
strcat ( query , geo_col_name ) ;
strcat ( query , " )) from " ) ;
2001-10-04 18:53:33 +00:00
strcat ( query , table ) ;
2001-09-19 18:47:32 +00:00
res3 = PQexec ( conn , query ) ;
if ( PQntuples ( res3 ) = = 1 ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res3 , 0 , 0 ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res3 , 0 , 0 ) , strlen ( PQgetvalue ( res3 , 0 , 0 ) ) + 1 ) ;
} else if ( PQntuples ( res3 ) > 1 ) {
2001-09-20 18:14:43 +00:00
printf ( " ERROR: Cannot have multiple geometry types in a shapefile. \n Use option -t(unimplemented currently,sorry...) to specify what type of geometry you want dumped \n \n " ) ;
exit_nicely ( conn ) ;
2001-09-19 18:47:32 +00:00
} else {
printf ( " ERROR: Cannot determine geometry type of table. \n " ) ;
exit_nicely ( conn ) ;
}
geo_str_left = ( char * ) malloc ( 10 ) ;
strncpy ( geo_str_left , geo_str , 8 ) ;
free ( geo_str ) ;
if ( strncmp ( geo_str_left , " MULTILIN " , 8 ) = = 0 ) {
//multilinestring ---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_ARC ) ; //2d line shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_ARCZ ) ; //3d line shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_multilines ( geo_str , i , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing multiline to shape file " ) ;
}
2001-10-04 18:53:33 +00:00
if ( i % 50 = = 1 ) {
2001-09-19 18:47:32 +00:00
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else if ( strncmp ( geo_str_left , " LINESTRI " , 8 ) = = 0 ) {
//linestring---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_ARC ) ; //2d lines shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_ARCZ ) ; //3d lines shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_lines ( geo_str , i , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing line to shape file " ) ;
}
if ( i % 100 = = 0 ) {
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else if ( strncmp ( geo_str_left , " POLYGON " , 7 ) = = 0 ) {
//Polygon---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_POLYGON ) ; //2d lines shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_POLYGONZ ) ; //3d lines shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_polygons ( geo_str , i , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing polygon to shape file " ) ;
}
if ( i % 100 = = 0 ) {
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else if ( strncmp ( geo_str_left , " MULTIPOL " , 8 ) = = 0 ) {
//multipolygon---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_POLYGON ) ; //2d polygon shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_POLYGONZ ) ; //3d polygon shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_multipolygons ( geo_str , i , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing polygon to shape file " ) ;
}
if ( i % 100 = = 0 ) {
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else if ( strncmp ( geo_str_left , " POINT " , 5 ) = = 0 ) {
//point---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_POINT ) ; //2d point shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_POINTZ ) ; //3d point shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_points ( geo_str , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing line to shape file " ) ;
}
if ( i % 100 = = 0 ) {
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else if ( strncmp ( geo_str_left , " MULTIPOI " , 8 ) = = 0 ) {
//multipoint---------------------------------------------------
2001-10-04 18:53:33 +00:00
if ( is3d = = 0 ) {
shp = SHPCreate ( shp_file , SHPT_MULTIPOINT ) ; //2d point shp file
2001-09-19 18:47:32 +00:00
} else {
2001-10-04 18:53:33 +00:00
shp = SHPCreate ( shp_file , SHPT_MULTIPOINTZ ) ; //3d point shp file
2001-09-19 18:47:32 +00:00
}
for ( i = 0 ; i < PQntuples ( res ) ; i + + ) {
geo_str = ( char * ) malloc ( strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
memcpy ( geo_str , ( char * ) PQgetvalue ( res , i , geovalue_field ) , strlen ( PQgetvalue ( res , i , geovalue_field ) ) + 1 ) ;
2001-10-04 18:53:33 +00:00
if ( create_multipoints ( geo_str , shp , is3d ) = = 0 ) {
2001-09-19 18:47:32 +00:00
printf ( " Error writing line to shape file " ) ;
}
if ( i % 100 = = 0 ) {
printf ( " shape - %d added \n " , i ) ;
}
free ( geo_str ) ;
}
2001-10-04 18:53:33 +00:00
printf ( " shape - %d added \n " , i ) ;
2001-09-19 18:47:32 +00:00
} else {
printf ( " type '%s' is not Supported at this time. \n The DBF file has been created but not the shx or shp files. \n " , geo_str_left ) ;
shp = NULL ;
}
if ( shp ! = NULL ) {
SHPClose ( shp ) ;
}
free ( geo_str_left ) ;
PQclear ( res ) ;
/* close the connection to the database and cleanup */
PQfinish ( conn ) ;
# ifdef DEBUG
fclose ( debug ) ;
# endif /* DEBUG */
return 0 ;
}
//reads points into x,y,z co-ord arrays
int parse_points ( char * str , int num_points , double * x , double * y , double * z ) {
int keep_going ;
int num_found = 0 ;
char * end_of_double ;
if ( ( str = = NULL ) | | ( str [ 0 ] = = 0 ) ) {
return 0 ; //either null string or empty string
}
//look ahead for the "("
str = strchr ( str , ' ( ' ) ;
if ( ( str = = NULL ) | | ( str [ 1 ] = = 0 ) ) { // str[0] = '(';
return 0 ; //either didnt find "(" or its at the end of the string
}
str + + ; //move forward one char
keep_going = 1 ;
while ( keep_going = = 1 ) {
//attempt to get the point
//scanf is slow, so we use strtod()
x [ num_found ] = ( double ) strtod ( str , & end_of_double ) ;
if ( end_of_double = = str ) {
return 0 ; //error occured (nothing parsed)
}
str = end_of_double ;
y [ num_found ] = strtod ( str , & end_of_double ) ;
if ( end_of_double = = str ) {
return 0 ; //error occured (nothing parsed)
}
str = end_of_double ;
z [ num_found ] = strtod ( str , & end_of_double ) ; //will be zero if error occured
str = end_of_double ;
num_found + + ;
str = strpbrk ( str , " ,) " ) ; // look for a "," or ")"
if ( str ! = NULL & & str [ 0 ] = = ' , ' ) {
str + + ;
}
keep_going = ( str ! = NULL ) & & ( str [ 0 ] ! = ' ) ' ) ;
}
return num_found ;
}
//returns how many points are in the first list in str
//
// 1. scan ahead looking for "("
// 2. find "," until hit a ")"
// 3. return number of points found
//
// NOTE: doesnt actually parse the points, so if the
// str contains an invalid geometry, this could give
// back the wrong answer.
//
// "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" => 2 (2nd list is not included)
2001-09-20 18:14:43 +00:00
int num_points ( char * str ) {
2001-09-19 18:47:32 +00:00
int keep_going ;
int points_found = 1 ; //no "," if only one point (and last point)
if ( ( str = = NULL ) | | ( str [ 0 ] = = 0 ) )
{
return 0 ; //either null string or empty string
}
//look ahead for the "("
str = strchr ( str , ' ( ' ) ;
if ( ( str = = NULL ) | | ( str [ 1 ] = = 0 ) ) // str[0] = '(';
{
return 0 ; //either didnt find "(" or its at the end of the string
}
keep_going = 1 ;
while ( keep_going )
{
str = strpbrk ( str , " ,) " ) ; // look for a "," or ")"
keep_going = ( str ! = NULL ) ;
if ( keep_going ) // found a , or )
{
if ( str [ 0 ] = = ' ) ' )
{
//finished
return points_found ;
}
else //str[0] = ","
{
points_found + + ;
str + + ; //move 1 char forward
}
}
}
return points_found ; // technically it should return an error.
}
//number of sublist in a string.
// Find the number of lines in a Multiline
// OR
// The number of rings in a Polygon
// OR
// The number of polygons in a multipolygon
// ( (..),(..),(..) ) -> 3
// ( ( (..),(..) ), ( (..) )) -> 2
// ( ) -> 0
// scan through the list, for every "(", depth (nesting) increases by 1
// for every ")", depth (nesting) decreases by 1
// if find a "(" at depth 1, then there is a sub list
//
// example:
// "(((..),(..)),((..)))"
//depth 12333223332112333210
// + + increase here
2001-09-20 18:14:43 +00:00
int num_lines ( char * str ) {
2001-09-19 18:47:32 +00:00
int current_depth = 0 ;
int numb_lists = 0 ;
while ( ( str ! = NULL ) & & ( str [ 0 ] ! = 0 ) )
{
str = strpbrk ( str , " () " ) ; //look for "(" or ")"
if ( str ! = NULL )
{
if ( str [ 0 ] = = ' ( ' )
{
current_depth + + ;
if ( current_depth = = 2 )
numb_lists + + ;
}
if ( str [ 0 ] = = ' ) ' )
{
current_depth - - ;
if ( current_depth = = 0 )
return numb_lists ;
}
str + + ;
}
}
return numb_lists ; // probably should give an error
}
//simple scan-forward to find the next "(" at the same level
// ( (), (),(), ),(...
// + return this location
2001-09-20 18:14:43 +00:00
char * scan_to_same_level ( char * str ) {
2001-09-19 18:47:32 +00:00
//scan forward in string looking for at "(" at the same level
// as the one its already pointing at
int current_depth = 0 ;
int first_one = 1 ;
while ( ( str ! = NULL ) & & ( str [ 0 ] ! = 0 ) )
{
str = strpbrk ( str , " () " ) ;
if ( str ! = NULL )
{
if ( str [ 0 ] = = ' ( ' )
{
if ( ! ( first_one ) )
{
if ( current_depth = = 0 )
return str ;
}
else
first_one = 0 ; //ignore the first opening "("
current_depth + + ;
}
if ( str [ 0 ] = = ' ) ' )
{
current_depth - - ;
}
str + + ;
}
}
return str ; // probably should give an error
}
// Find out how many points are in each sublist, put the result in the array npoints[]
// (for at most max_list sublists)
//
// ( (L1),(L2),(L3) ) --> npoints[0] = points in L1,
// npoints[1] = points in L2,
// npoints[2] = points in L3
//
// We find these by, again, scanning through str looking for "(" and ")"
// to determine the current depth. We dont actually parse the points.
int points_per_sublist ( char * str , int * npoints , long max_lists ) {
//scan through, noting depth and ","s
int current_depth = 0 ;
int current_list = - 1 ;
while ( ( str ! = NULL ) & & ( str [ 0 ] ! = 0 ) )
{
str = strpbrk ( str , " (), " ) ; //find "(" or ")" or ","
if ( str ! = NULL )
{
if ( str [ 0 ] = = ' ( ' )
{
current_depth + + ;
if ( current_depth = = 2 )
{
current_list + + ;
if ( current_list > = max_lists )
return 1 ; // too many sub lists found
npoints [ current_list ] = 1 ;
}
// might want to return an error if depth>2
}
if ( str [ 0 ] = = ' ) ' )
{
current_depth - - ;
if ( current_depth = = 0 )
return 1 ;
}
if ( str [ 0 ] = = ' , ' )
{
if ( current_depth = = 2 )
{
npoints [ current_list ] + + ;
}
}
str + + ;
}
}
return 1 ; // probably should give an error
}
2001-10-04 18:53:33 +00:00
int create_multilines ( char * str , int shape_id , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
int lines , i , j , max_points , index ;
int * points ;
int * part_index ;
double * x ;
double * y ;
double * z ;
double * totx ;
double * toty ;
double * totz ;
SHPObject * obj ;
lines = num_lines ( str ) ;
points = ( int * ) malloc ( sizeof ( int ) * lines ) ;
if ( points_per_sublist ( str , points , lines ) = = 0 ) {
printf ( " error - points_per_sublist failed " ) ;
}
max_points = 0 ;
for ( j = 0 ; j < lines ; j + + ) {
max_points + = points [ j ] ;
}
part_index = ( int * ) malloc ( sizeof ( int ) * lines ) ;
totx = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
toty = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
totz = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
index = 0 ;
for ( i = 0 ; i < lines ; i + + ) {
str = strchr ( str , ' ( ' ) ;
if ( str [ 0 ] = = ' ( ' & & str [ 1 ] = = ' ( ' ) {
str + + ;
}
x = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
y = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
z = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
parse_points ( str , points [ i ] , x , y , z ) ;
str = scan_to_same_level ( str ) ;
part_index [ i ] = index ;
for ( j = 0 ; j < points [ i ] ; j + + ) {
totx [ index ] = x [ j ] ;
toty [ index ] = y [ j ] ;
totz [ index ] = z [ j ] ;
index + + ;
}
free ( x ) ;
free ( y ) ;
free ( z ) ;
}
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateObject ( SHPT_ARC , shape_id , lines , part_index , NULL , max_points , totx , toty , totz , NULL ) ;
} else {
obj = SHPCreateObject ( SHPT_ARCZ , shape_id , lines , part_index , NULL , max_points , totx , toty , totz , NULL ) ;
}
free ( part_index ) ;
free ( points ) ;
free ( totx ) ;
free ( toty ) ;
free ( totz ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}
2001-10-04 18:53:33 +00:00
int create_lines ( char * str , int shape_id , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
int points ;
int * part_index ;
double * x ,
* y ,
* z ;
SHPObject * obj ;
part_index = ( int * ) malloc ( sizeof ( int ) ) ; //we know lines only have 1 part so make the array of size 1
part_index [ 0 ] = 0 ;
points = num_points ( str ) ;
x = ( double * ) malloc ( sizeof ( double ) * points ) ;
y = ( double * ) malloc ( sizeof ( double ) * points ) ;
z = ( double * ) malloc ( sizeof ( double ) * points ) ;
parse_points ( str , points , x , y , z ) ;
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateObject ( SHPT_ARC , shape_id , 1 , part_index , NULL , points , x , y , z , NULL ) ;
} else {
obj = SHPCreateObject ( SHPT_ARCZ , shape_id , 1 , part_index , NULL , points , x , y , z , NULL ) ;
}
free ( part_index ) ;
free ( x ) ;
free ( y ) ;
free ( z ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}
2001-10-04 18:53:33 +00:00
int create_points ( char * str , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
double * x ,
* y ,
* z ;
SHPObject * obj ;
x = ( double * ) malloc ( sizeof ( double ) ) ;
y = ( double * ) malloc ( sizeof ( double ) ) ;
z = ( double * ) malloc ( sizeof ( double ) ) ;
parse_points ( str , 1 , x , y , z ) ;
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateSimpleObject ( SHPT_POINT , 1 , x , y , z ) ;
} else {
obj = SHPCreateSimpleObject ( SHPT_POINTZ , 1 , x , y , z ) ;
}
free ( x ) ;
free ( y ) ;
free ( z ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}
2001-10-04 18:53:33 +00:00
int create_multipoints ( char * str , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
int points ;
double * x ,
* y ,
* z ;
SHPObject * obj ;
points = num_points ( str ) ;
x = ( double * ) malloc ( sizeof ( double ) * points ) ;
y = ( double * ) malloc ( sizeof ( double ) * points ) ;
z = ( double * ) malloc ( sizeof ( double ) * points ) ;
parse_points ( str , points , x , y , z ) ;
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateSimpleObject ( SHPT_MULTIPOINT , 1 , x , y , z ) ;
} else {
obj = SHPCreateSimpleObject ( SHPT_MULTIPOINTZ , 1 , x , y , z ) ;
}
free ( x ) ;
free ( y ) ;
free ( z ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}
2001-10-04 18:53:33 +00:00
int create_polygons ( char * str , int shape_id , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
int rings , i , j , max_points , index ;
int * points ;
int * part_index ;
double * x ;
double * y ;
double * z ;
double * totx ;
double * toty ;
double * totz ;
SHPObject * obj ;
rings = num_lines ( str ) ; //the number of rings in the polygon
points = ( int * ) malloc ( sizeof ( int ) * rings ) ;
if ( points_per_sublist ( str , points , rings ) = = 0 ) {
printf ( " error - points_per_sublist failed " ) ;
}
max_points = 0 ;
for ( j = 0 ; j < rings ; j + + ) {
max_points + = points [ j ] ;
}
part_index = ( int * ) malloc ( sizeof ( int ) * rings ) ;
totx = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
toty = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
totz = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
index = 0 ;
for ( i = 0 ; i < rings ; i + + ) {
str = strchr ( str , ' ( ' ) ;
if ( str [ 0 ] = = ' ( ' & & str [ 1 ] = = ' ( ' ) {
str + + ;
}
x = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
y = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
z = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
parse_points ( str , points [ i ] , x , y , z ) ;
str = scan_to_same_level ( str ) ;
part_index [ i ] = index ;
for ( j = 0 ; j < points [ i ] ; j + + ) {
totx [ index ] = x [ j ] ;
toty [ index ] = y [ j ] ;
totz [ index ] = z [ j ] ;
index + + ;
}
free ( x ) ;
free ( y ) ;
free ( z ) ;
}
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateObject ( SHPT_POLYGON , shape_id , rings , part_index , NULL , max_points , totx , toty , totz , NULL ) ;
} else {
obj = SHPCreateObject ( SHPT_POLYGONZ , shape_id , rings , part_index , NULL , max_points , totx , toty , totz , NULL ) ;
}
free ( part_index ) ;
free ( points ) ;
free ( totx ) ;
free ( toty ) ;
free ( totz ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}
2001-10-04 18:53:33 +00:00
int create_multipolygons ( char * str , int shape_id , SHPHandle shp , int dims ) {
2001-09-19 18:47:32 +00:00
int polys , rings , i , j , k , max_points ;
int index , indexk , index2part , tot_rings , final_max_points ;
int * points ;
int * part_index ;
int * final_part_index ;
char * temp ;
char * temp_addr ;
double * x ;
double * y ;
double * z ;
double * totx ;
double * toty ;
double * totz ;
double * finalx ;
double * finaly ;
double * finalz ;
SHPObject * obj ;
2001-10-11 18:07:33 +00:00
points = 0 ;
2001-09-19 18:47:32 +00:00
polys = num_lines ( str ) ; //the number of rings in the polygon
final_max_points = 0 ;
temp_addr = ( char * ) malloc ( strlen ( str ) + 1 ) ;
temp = temp_addr ; //keep original pointer to free the mem later
strcpy ( temp , str ) ;
tot_rings = 0 ;
index2part = 0 ;
indexk = 0 ;
for ( i = 0 ; i < polys ; i + + ) {
temp = strstr ( temp , " (( " ) ;
if ( temp [ 0 ] = = ' ( ' & & temp [ 1 ] = = ' ( ' & & temp [ 2 ] = = ' ( ' ) {
temp + + ;
}
rings = num_lines ( temp ) ;
points = ( int * ) malloc ( sizeof ( int ) * rings ) ;
points_per_sublist ( temp , points , rings ) ;
tot_rings + = rings ;
for ( j = 0 ; j < rings ; j + + ) {
final_max_points + = points [ j ] ;
}
temp + = 2 ;
}
free ( points ) ;
temp = temp_addr ;
final_part_index = ( int * ) malloc ( sizeof ( int ) * tot_rings ) ;
finalx = ( double * ) malloc ( sizeof ( double ) * final_max_points ) ;
finaly = ( double * ) malloc ( sizeof ( double ) * final_max_points ) ;
finalz = ( double * ) malloc ( sizeof ( double ) * final_max_points ) ;
for ( k = 0 ; k < polys ; k + + ) { //for each polygon
str = strstr ( str , " (( " ) ;
if ( strlen ( str ) > 2 & & str [ 0 ] = = ' ( ' & & str [ 1 ] = = ' ( ' & & str [ 2 ] = = ' ( ' ) {
str + + ;
}
rings = num_lines ( str ) ;
points = ( int * ) malloc ( sizeof ( int ) * rings ) ;
if ( points_per_sublist ( str , points , rings ) = = 0 ) {
printf ( " error - points_per_sublist failed " ) ;
}
max_points = 0 ;
for ( j = 0 ; j < rings ; j + + ) {
max_points + = points [ j ] ;
}
part_index = ( int * ) malloc ( sizeof ( int ) * rings ) ;
totx = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
toty = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
totz = ( double * ) malloc ( sizeof ( double ) * max_points ) ;
index = 0 ;
for ( i = 0 ; i < rings ; i + + ) {
str = strchr ( str , ' ( ' ) ;
if ( str [ 0 ] = = ' ( ' & & str [ 1 ] = = ' ( ' ) {
str + + ;
}
x = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
y = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
z = ( double * ) malloc ( sizeof ( double ) * points [ i ] ) ;
parse_points ( str , points [ i ] , x , y , z ) ;
str = scan_to_same_level ( str ) ;
part_index [ i ] = index ;
for ( j = 0 ; j < points [ i ] ; j + + ) {
totx [ index ] = x [ j ] ;
toty [ index ] = y [ j ] ;
totz [ index ] = z [ j ] ;
index + + ;
}
free ( x ) ;
free ( y ) ;
free ( z ) ;
}
for ( j = 0 ; j < i ; j + + ) {
final_part_index [ index2part ] = part_index [ j ] + indexk ;
index2part + + ;
}
for ( j = 0 ; j < index ; j + + ) {
finalx [ indexk ] = totx [ j ] ;
finaly [ indexk ] = toty [ j ] ;
finalz [ indexk ] = totz [ j ] ;
indexk + + ;
}
free ( points ) ;
free ( part_index ) ;
free ( totx ) ;
free ( toty ) ;
free ( totz ) ;
str - = 1 ;
} //end for (k...
obj = ( SHPObject * ) malloc ( sizeof ( SHPObject ) ) ;
2001-10-04 18:53:33 +00:00
if ( dims = = 0 ) {
2001-09-19 18:47:32 +00:00
obj = SHPCreateObject ( SHPT_POLYGON , shape_id , tot_rings , final_part_index , NULL , final_max_points , finalx , finaly , finalz , NULL ) ;
} else {
obj = SHPCreateObject ( SHPT_POLYGONZ , shape_id , tot_rings , final_part_index , NULL , final_max_points , finalx , finaly , finalz , NULL ) ;
}
free ( final_part_index ) ;
free ( finalx ) ;
free ( finaly ) ;
free ( finalz ) ;
if ( SHPWriteObject ( shp , - 1 , obj ) ! = - 1 ) {
SHPDestroyObject ( obj ) ;
return 1 ;
} else {
SHPDestroyObject ( obj ) ;
return 0 ;
}
}