1

I want to convert the geometry to well known binary (WKB) format of my shapefile. I want to print and want to write it into another shapefile.

My code is:

#include <stdio.h>
#include <stdlib.h>
#include <ogr_api.h>
#include <cpl_conv.h>
#include <cpl_port.h>
#include <gdal.h>
#include <string.h>
#include <gdal_utils.h>
#include <cpl_progress.h>
#include <cpl_minixml.h>
#include <ogr_core.h>
int main()
{
    char path1[200],path2[200],filename1[]="/1.shp",filename2[]="/g_copy.shp";
    unsigned char *buf;
    char *sz;
    GDALDatasetH inShapeDS;
    OGRLayerH inShapeLayer;
    OGRFeatureH inShapeFeature;
    OGRFeatureDefnH inFeatureDefn;
    OGRFieldDefnH inFieldDefn;

    int inFieldCount;
    OGRGeometryH inShapeGeometry;

    GDALAllRegister();

    getcwd(path1, sizeof(path1));
    strcpy(path2,path1);
    strcat(path1,filename1);
    strcat(path2,filename2);

    inShapeDS = GDALOpenEx(path1, GDAL_OF_VECTOR, NULL, NULL, NULL );
    if( inShapeDS == NULL )
    {
        printf( "Open failed.\n" );
        exit( 1 );
    }

    printf("number of layers:%d\n",GDALDatasetGetLayerCount(inShapeDS));

    inShapeLayer = GDALDatasetGetLayerByName(inShapeDS, "1");

    inFeatureDefn = OGR_L_GetLayerDefn(inShapeLayer);
    printf("number of features in this layer:%d\n",OGR_L_GetFeatureCount(inShapeLayer,1));  

    inShapeFeature = OGR_L_GetNextFeature(inShapeLayer);

    inShapeGeometry = OGR_F_GetGeometryRef(inShapeFeature);

    printf("size of binary geom:%d\n",OGR_G_WkbSize(inShapeGeometry));  

    buf = (unsigned char *)CPLMalloc(OGR_G_WkbSize(inShapeGeometry));

    OGR_G_ExportToWkb(inShapeGeometry,wkbXDR,buf);

    //sz=buf;
    sz = (char *)buf;

    printf("binary geom:%s",sz);


    const char *pszDriverName = "ESRI Shapefile";
    GDALDriverH outDriver;
    GDALDatasetH outDS;
    OGRLayerH outLayer;
    OGRFieldDefnH outFieldDefn;


    outDriver = GDALGetDriverByName( pszDriverName );
    if( outDriver == NULL )
    {
        printf( "%s driver not available.\n", pszDriverName );
        exit( 1 );
    }
    outDS = GDALCreate( outDriver, path2, 0, 0, 0, GDT_Unknown, NULL );
    if( outDS == NULL )
    {
        printf( "Creation of output file failed.\n" );
        exit( 1 );
    }
    outLayer = GDALDatasetCreateLayer( outDS, "g_copy", NULL, wkbUnknown, NULL );
    if( outLayer == NULL )
    {
        printf( "Layer creation failed.\n" );
        exit( 1 );
    }

    outFieldDefn = OGR_Fld_Create( "GeomB", OFTString );
    OGR_Fld_SetWidth( outFieldDefn, (OGR_G_WkbSize(inShapeGeometry)));
    if( OGR_L_CreateField( outLayer, outFieldDefn, TRUE ) != OGRERR_NONE )
    {
        printf( "Creating Name field failed.\n" );
        exit( 1 );
    }
    OGR_Fld_Destroy(outFieldDefn);

    OGRFeatureH outFeature;
    outFeature = OGR_F_Create( OGR_L_GetLayerDefn( outLayer ) );
    OGR_F_SetFieldString( outFeature, OGR_F_GetFieldIndex(outFeature, "GeomB"), sz );

    if( OGR_L_CreateFeature( outLayer, outFeature ) != OGRERR_NONE )
    {
        printf( "Failed to create feature in shapefile.\n" );
        exit( 1 );
    }
    OGR_F_Destroy( outFeature );

    CPLFree(buf);
    OGR_F_Destroy(inShapeFeature);

    GDALClose(inShapeDS);

    return 0;
}

Now the problem is in print function, it is giving some symbol. And in the newly created shapefile, it is not printing anything. Another thing that in the new shapefile the width of the GeomB field is truncated to 254, but the width of binary version of the geom is almost 2000 bits.

It is getting very much difficult in C. How to fix it?

2

OGRwkbByteOrder

(docs on eByteOrder)

You are likely wanting to use wkbNDR, which is enum 1, assuming you are running on an intel architecture.

invalid conversion error

(docs on OGR_G_ExportToWkb())

Without having the full error message, it looks like OGR_G_ExportToWkb() takes an unsigned char*, and you dereference buf (which is an unsigned char*) to become an unsigned char. I think it should look like this:

OGR_G_ExportToWkb(inShapeGeometry,eOrder,buf);

(docs on OGR_G_ExportToWkt())

For OGR_G_ExportToWkt(), it looks like the buffer is specified as a char**, or a pointer to a char-pointer. In your case, you should provide the address of the char* buff. What you are currently doing is dereferencing buff, which provides a char.

OGR_G_ExportToWkt(inShapeGeometry,&buff);

Proper functioning

This is the baseline to get the program compiling, I think. If you look at the docs, you will see a better description of what these buffers are doing. In the case of exportToWkb(), you need to ensure the buffer is atleast OGRGeometry::WkbSize() long, so declaring the length of the buffer at the top of the program might not be the best idea (or maybe 100 characters is fine if you have a very small geometry set). In the case of exportToWkt(), a new char buffer is created by the function and the char** (&buff for you) is set to point to that buffer. This means you don't need to allocate memory for buff at the top of the program. Just make buff an unassigned char**.

// stuff
char** buff;

//stuff

OGR_G_ExportToWkt(inShapeGeometry, buff);
  • modified the code in my question. Please check again. – LSG Feb 17 '17 at 15:36
  • @LSG The error message says it all. The compiler is unable to convert an unsigned char into an unsigned char*. You are still dereferencing buf in the call to OGR_G_ExportToWkb(inShapeGeometry,wkbNDR,*buf); When you put an asterisk before buf you are returning an unsigned char. The function needs an unsigned char*. Do not put the asterisk in front of buf. – Logan Byers Feb 17 '17 at 15:51
  • Ok, tried with that, but it got hanged. Now tried again without the print and it is fine. So, some problem with the print. printf("binary geom:%s",*buf); --> stopped working, printf("binary geom:%s",buf); --> prints symbol, printf("binary geom:%c",*buf); -->prints symbol, printf("binary geom:%u",*buf); --> prints 1. What is this 1? – LSG Feb 17 '17 at 16:24
  • Edited a lot in the code – LSG Feb 20 '17 at 11:50
  • @LSG Printing an array of char (binary data) won't always behave like you expect. printf needs to be null-terminated, I think. Don't print buf. Write it to a file. Look at the WKB format standard to understand what WKB looks like and how it does not look like a string of chars. – Logan Byers Feb 20 '17 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.