Wednesday, May 29, 2013

GDAL 1.9.2 OGR plugin driver for GeoMedia MDB

GDAL 1.9.2 latest stable release provide support for GeoMedia Acccess DB reading capability. GDAL uses jackcess jar in order to   read tables inside MDB store. However it does not properly read GeoMedia metadata and coordinate system information. Text , line geometry reading is not supported. GDAL mdb driver only supports Albers Conical projection as of now.

On linux, user can build the GDAL provided mdb driver by configuring --with-mdb flag associated with JVM lib settings. By this actually GDAL creates a dependency over jvm so/dll. 

For windows compilation you have to create a makefile.vc for mdb driver. Also you need to update nmake.opt to include jvm lib as dependent library. Update ogrsf_frmts makefile to include mdb obj files for ogr lib generation.

I did not want to make any modification over GDAL code which will actually put me in trouble while upgrading to new library. To make my modification detached from original GDAL code, I have created a new ogr driver for MDB. My new driver ,say roltamdb, which solves all metadata reading issues and supports variety of projections like PC, LCC, MER etc.. and it also supports TextPointGeometry and LineGeometry reading capability.

Over windows I'm able to create separate dll ogr_roltamdb.dll using gdal_i.lib and jvm.lib. I have set the OGR_DRIVER_PATH environment variable to locate my new dll. Now while I invoked "ogrinfo --formats" command, my driver is listed by ogr/gdal.

Initially I had lots of issue in building the new driver over linux 64bit machine, like LD_SHARED is not configured, not able to find main etc. While searching the web for resolution, noticed that lots of people having the same headache. I lost one day to figure out the problem. BTW I'm new to linux development. See the details below if anyone want to create your own OGR driver as a separate plugin.

For linux 64bit compile you need to configure GDAL first

# export CFLAGS="-fPIC -m64"
# export CXXFLAGS="-fPIC -m64"
# ./configure --with-java=/home/jdk1.6.0_43 --with-jvm-lib=/home/jdk1.6.0_43/jre/lib/amd64/server -enable-shared -with-pic --without-libtool
# make -j8
# make install

Create a new GNUmakefile for the new driver(roltamdb) as below -

--------------------------------------------------------------
include ../../../GDALmake.opt

OBJ     =       ogrroltamdbdatasource.o ogrroltamdblayer.o ogrroltamdbdriver.o \
                ogrroltamdbjackcess.o ogrroltageomediageometry.o

CPPFLAGS        :=      -I.. $(GDAL_INCLUDE) $(JAVA_INC) $(CPPFLAGS)

PLUGIN_SO =     ogr_roltamdb.so

JVM_LIB =        -L/home/jdk1.6.0_43/jre/lib/amd64/server -ljvm

default:        $(OBJ:.o=.$(OBJ_EXT)) plugin

clean:
        rm -f *.o $(O_OBJ) *.so *.lo

install-obj:    $(O_OBJ:.o=.$(OBJ_EXT))

$(OBJ) $(O_OBJ):        ogr_mdb.h

plugin: $(PLUGIN_SO)

$(PLUGIN_SO):   $(OBJ)
        $(LD_SHARED) $(OBJ) $(GDAL_SLIB_LINK) \
        $(JVM_LIB) -o $(PLUGIN_SO)

install: plugin
         $(INSTALL_LIB) $(PLUGIN_SO) $(DESTDIR)$(INST_LIB)

-------------------------------------------------------------

# make 
# make install

Your new driver should be up and running!! Enjoy..  

Wednesday, March 20, 2013

Add two big numbers


A simple program to add two big numbers -

#include <iostream>
#include <string>
using namespace std;

string add(string str1,string str2)
{
string sumstr;

string minstr,maxstr;
if(str1.length() !=str2.length())
{
maxstr = str1.length()>str2.length()?str1:str2;
minstr = str1.length()<str2.length()?str1:str2;
}
else
{
maxstr = str1;
minstr = str2;
}

sumstr = "0"+ maxstr;

string::reverse_iterator minrev = minstr.rbegin();
string::reverse_iterator maxrev = maxstr.rbegin();

string::reverse_iterator sumrev = sumstr.rbegin();
int carry = 0;
while(minrev != minstr.rend())
{
*sumrev += *minrev - '0' + carry;
if(*sumrev > '9')
{
*sumrev -= 10;
carry = 1;
}
else
{
carry = 0;
}
++sumrev;
++minrev;
}

while(sumrev != sumstr.rend() && carry ==1)
{
*sumrev += 1;
if(*sumrev > '9')
{
*sumrev -= 10;
*(sumrev+1) += 1;

if(*(sumrev+1) < '9')
carry = 0;
else
*(sumrev+1) -= 1;
}
else
carry = 0;

++sumrev;
}

if(sumstr.at(0) == '0')
sumstr.erase(0,1);

return sumstr;
}

int main(int argc, char* argv[])
{
while(1)
{
string str1,str2;
cout<<"Enter number1: ";
cin >> str1;
cout<<"Enter number2: ";
cin >> str2;

string result = add(str1,str2);

cout<<"Result: "<<result<<endl;
}
return 0;
}