From David Callu, added DBase attribute support for shapefiles

This commit is contained in:
Robert Osfield 2007-12-09 15:43:49 +00:00
parent 5e6bab7de1
commit 78c1fd4844
10 changed files with 716 additions and 7 deletions

View File

@ -0,0 +1,101 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGSIM_SHAPEATTRIBUTE
#define OSGSIM_SHAPEATTRIBUTE 1
#include <string>
#include <vector>
#include <osg/Object>
namespace osgSim
{
class ShapeAttribute
{
public:
enum Type
{
UNKNOW,
INTEGER,
DOUBLE,
STRING
};
ShapeAttribute();
ShapeAttribute(const char * name);
ShapeAttribute(const char * name, int value);
ShapeAttribute(const char * name, double value);
ShapeAttribute(const char * name, const char * value);
ShapeAttribute(const ShapeAttribute & sa);
~ShapeAttribute();
const std::string & getName() const { return _name; }
const Type getType() const { return _type; }
int getInt() const { return _integer; }
double getDouble() const { return _double; }
const char * getString() const { return _string; }
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
int compare(const osgSim::ShapeAttribute& sa) const;
private:
std::string _name;
Type _type;
union
{
int _integer;
double _double;
char * _string;
};
};
class ShapeAttributeList : public osg::Object, public std::vector<ShapeAttribute>
{
public:
META_Object(osgSim, ShapeAttributeList)
ShapeAttributeList():
Object()
{}
/** Copy constructor, optional CopyOp object can be used to control
* shallow vs deep copying of dynamic data.*/
ShapeAttributeList(const ShapeAttributeList& sal,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
osg::Object(sal, copyop)
{
copy(sal.begin(),sal.end(), begin());
}
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
virtual int compare(const osgSim::ShapeAttributeList& sal) const;
protected:
virtual ~ShapeAttributeList() {}
};
}
#endif // ** SHAPEATTRIBUTE_ ** //

View File

@ -2,6 +2,7 @@
SET(TARGET_SRC
IO_ShapeAttribute.cpp
IO_BlinkSequence.cpp
IO_DOFTransform.cpp
IO_Impostor.cpp

View File

@ -0,0 +1,169 @@
#include <osgSim/ShapeAttribute>
#include <iostream>
#include <string>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>
using namespace osgSim;
bool ShapeAttributeList_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ShapeAttributeList_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy ShapeAttributeList_Proxy
(
new ShapeAttributeList,
"ShapeAttributeList",
"Object ShapeAttributeList",
&ShapeAttributeList_readLocalData,
&ShapeAttributeList_writeLocalData,
osgDB::DotOsgWrapper::READ_AND_WRITE
);
osgSim::ShapeAttribute::Type ShapeAttributeList_typeStringToEnum(std::string type)
{
if (type == "STRING") return osgSim::ShapeAttribute::STRING;
else if (type == "DOUBLE") return osgSim::ShapeAttribute::DOUBLE;
else if (type == "INTEGER") return osgSim::ShapeAttribute::INTEGER;
else return osgSim::ShapeAttribute::UNKNOW;
}
void ShapeAttributeList_typeEnumToString(osgSim::ShapeAttribute::Type type, std::string & typeStr)
{
switch (type)
{
case osgSim::ShapeAttribute::STRING: typeStr = "STRING"; break;
case osgSim::ShapeAttribute::DOUBLE: typeStr = "DOUBLE"; break;
case osgSim::ShapeAttribute::INTEGER: typeStr = "INTEGER"; break;
default: typeStr = "UNKNOW"; break;
}
}
bool ShapeAttributeList_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
bool iteratorAdvanced = false;
ShapeAttributeList &sal = static_cast<ShapeAttributeList &>(obj);
int size = 0;
if (fr[0].matchWord("size") && fr[1].getInt(size))
{
sal.reserve(size);
fr += 2;
iteratorAdvanced = true;
}
if (size)
{
std::string name;
osgSim::ShapeAttribute::Type type;
for (int i = 0; i < size; ++i)
{
if (fr.matchSequence("name %s"))
{
name = fr[1].getStr();
fr += 2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("type"))
{
type = ShapeAttributeList_typeStringToEnum(fr[1].getStr());
fr += 2;
iteratorAdvanced = true;
switch (type)
{
case osgSim::ShapeAttribute::STRING:
{
if (fr.matchSequence("value %s"))
{
std::string value = fr[1].getStr();
fr += 2;
iteratorAdvanced = true;
sal.push_back(osgSim::ShapeAttribute((const char *) name.c_str(), (char*) value.c_str()));
}
break;
}
case osgSim::ShapeAttribute::DOUBLE:
{
double value;
if (fr[0].matchWord("value") && fr[1].getFloat(value))
{
fr += 2;
iteratorAdvanced = true;
sal.push_back(osgSim::ShapeAttribute((const char *) name.c_str(), value));
}
break;
}
case osgSim::ShapeAttribute::INTEGER:
{
int value;
if (fr[0].matchWord("value") && fr[1].getInt(value))
{
fr += 2;
iteratorAdvanced = true;
sal.push_back(osgSim::ShapeAttribute((const char *) name.c_str(), value));
}
break;
}
case osgSim::ShapeAttribute::UNKNOW:
default:
{
sal.push_back(osgSim::ShapeAttribute((const char *) name.c_str()));
break;
}
}
}
}
}
return iteratorAdvanced;
}
bool ShapeAttributeList_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
const ShapeAttributeList &sal = static_cast<const ShapeAttributeList &>(obj);
unsigned int size = sal.size();
fw.indent()<<"size "<< size << std::endl;
if (size)
{
std::string type;
ShapeAttributeList::const_iterator it, end = sal.end();
for (it = sal.begin(); it != end; ++it)
{
fw.indent()<<"name \""<< it->getName() << "\"" << std::endl;
ShapeAttributeList_typeEnumToString(it->getType(), type);
fw.indent()<<"type "<< type << std::endl;
switch (it->getType())
{
case osgSim::ShapeAttribute::STRING:
{
fw.indent()<<"value \""<< it->getString() << "\"" << std::endl;
break;
}
case osgSim::ShapeAttribute::INTEGER:
{
fw.indent()<<"value "<< it->getInt() << std::endl;
break;
}
case osgSim::ShapeAttribute::DOUBLE:
{
fw.indent()<<"value "<< it->getDouble() << std::endl;
break;
}
case osgSim::ShapeAttribute::UNKNOW:
default: break;
}
}
}
return true;
}

View File

@ -1,7 +1,8 @@
#this file is automatically generated
SET(TARGET_SRC ESRIShape.cpp ESRIShapeParser.cpp ESRIShapeReaderWriter.cpp )
SET(TARGET_H ESRIShape.h ESRIShapeParser.h )
SET(TARGET_SRC ESRIShape.cpp ESRIShapeParser.cpp ESRIShapeReaderWriter.cpp XBaseParser.cpp)
SET(TARGET_H ESRIShape.h ESRIShapeParser.h XBaseParser.h)
SET(TARGET_ADDED_LIBRARIES osgSim )
#### end var setup ###
SETUP_PLUGIN(shp)

View File

@ -7,13 +7,10 @@
#endif
#include <osg/Referenced>
#include "ESRIType.h"
namespace ESRIShape {
typedef int Integer;
typedef short Short;
typedef unsigned char Byte;
typedef double Double;
typedef unsigned char * BytePtr;
enum ByteOrder {
LittleEndian,

View File

@ -0,0 +1,15 @@
#ifndef ESRITYPE_H_
#define ESRITYPE_H_
namespace ESRIShape {
typedef int Integer;
typedef short Short;
typedef unsigned char Byte;
typedef double Double;
typedef unsigned char * BytePtr;
}
#endif /*ESRITYPE_H_*/

View File

@ -0,0 +1,212 @@
#include "XBaseParser.h"
#include <vector>
#include <string>
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <stdio.h>
#include <io.h>
#else
#include <unistd.h>
#endif
#include <fcntl.h>
#include <osg/Notify>
namespace ESRIShape
{
void XBaseHeader::print()
{
osg::notify(osg::INFO) << "VersionNumber = " << (int) _versionNumber << std::endl
<< "LastUpdate = " << 1900 + (int) _lastUpdate[0] << "/" << (int) _lastUpdate[1] << "/" << (int) _lastUpdate[2] << std::endl
<< "NumRecord = " << _numRecord << std::endl
<< "HeaderLength = " << _headerLength << std::endl
<< "RecordLength = " << _recordLength << std::endl;
}
bool XBaseHeader::read(int fd)
{
int nbytes = 0;
if ((nbytes = ::read( fd, &_versionNumber, sizeof(_versionNumber))) <= 0) return false;
if ((nbytes = ::read( fd, &_lastUpdate, sizeof(_lastUpdate))) <= 0) return false;
if ((nbytes = ::read( fd, &_numRecord, sizeof(_numRecord))) <= 0) return false;
if ((nbytes = ::read( fd, &_headerLength, sizeof(_headerLength))) <= 0) return false;
if ((nbytes = ::read( fd, &_recordLength, sizeof(_recordLength))) <= 0) return false;
if ((nbytes = ::read( fd, &_reserved, sizeof(_reserved))) <= 0) return false;
if ((nbytes = ::read( fd, &_incompleteTransaction, sizeof(_incompleteTransaction))) <= 0) return false;
if ((nbytes = ::read( fd, &_encryptionFlag, sizeof(_encryptionFlag))) <= 0) return false;
if ((nbytes = ::read( fd, &_freeRecordThread, sizeof(_freeRecordThread))) <= 0) return false;
if ((nbytes = ::read( fd, &_reservedMultiUser, sizeof(_reservedMultiUser))) <= 0) return false;
if ((nbytes = ::read( fd, &_mdxflag, sizeof(_mdxflag))) <= 0) return false;
if ((nbytes = ::read( fd, &_languageDriver, sizeof(_languageDriver))) <= 0) return false;
if ((nbytes = ::read( fd, &_reserved2, sizeof(_reserved2))) <= 0) return false;
return true;
}
void XBaseFieldDescriptor::print()
{
osg::notify(osg::INFO) << "name = " << _name << std::endl
<< "type = " << _fieldType << std::endl
<< "length = " << (int) _fieldLength << std::endl
<< "decimalCount = " << (int) _decimalCount << std::endl
<< "workAreaID = " << (int) _workAreaID << std::endl
<< "setFieldFlag = " << (int) _setFieldFlag << std::endl
<< "indexFieldFlag = " << (int) _indexFieldFlag << std::endl;
}
bool XBaseFieldDescriptor::read(int fd)
{
int nbytes = 0;
if ((nbytes = ::read( fd, &_name, sizeof(_name))) <= 0) return false;
if ((nbytes = ::read( fd, &_fieldType, sizeof(_fieldType))) <= 0) return false;
if ((nbytes = ::read( fd, &_fieldDataAddress, sizeof(_fieldDataAddress))) <= 0) return false;
if ((nbytes = ::read( fd, &_fieldLength, sizeof(_fieldLength))) <= 0) return false;
if ((nbytes = ::read( fd, &_decimalCount, sizeof(_decimalCount))) <= 0) return false;
if ((nbytes = ::read( fd, &_reservedMultiUser, sizeof(_reservedMultiUser))) <= 0) return false;
if ((nbytes = ::read( fd, &_workAreaID, sizeof(_workAreaID))) <= 0) return false;
if ((nbytes = ::read( fd, &_reservedMultiUser2, sizeof(_reservedMultiUser2))) <= 0) return false;
if ((nbytes = ::read( fd, &_setFieldFlag, sizeof(_setFieldFlag))) <= 0) return false;
if ((nbytes = ::read( fd, &_reserved, sizeof(_reserved))) <= 0) return false;
if ((nbytes = ::read( fd, &_indexFieldFlag, sizeof(_indexFieldFlag))) <= 0) return false;
return true;
}
XBaseParser::XBaseParser(const std::string fileName):
_valid(false)
{
int fd = 0;
if (fileName.empty() == false)
{
#ifdef WIN32
if( (fd = open( fileName.c_str(), O_RDONLY | O_BINARY )) <= 0 )
#else
if( (fd = ::open( fileName.c_str(), O_RDONLY )) <= 0 )
#endif
{
perror( fileName.c_str() );
return ;
}
}
_valid = parse(fd);
}
bool XBaseParser::parse(int fd)
{
int nbytes;
XBaseHeader _xBaseHeader;
std::vector<XBaseFieldDescriptor> _xBaseFieldDescriptorList;
XBaseFieldDescriptor _xBaseFieldDescriptorTmp;
// ** read the header
if (_xBaseHeader.read(fd) == false) return false;
// _xBaseHeader.print();
// ** read field descriptor
bool fieldDescriptorDone = false;
Byte nullTerminator;
while (fieldDescriptorDone == false)
{
// ** store the field descriptor
if (_xBaseFieldDescriptorTmp.read(fd) == false) return false;
_xBaseFieldDescriptorList.push_back(_xBaseFieldDescriptorTmp);
// _xBaseFieldDescriptorTmp.print();
// ** check the terminator
if ((nbytes = ::read( fd, &nullTerminator, sizeof(nullTerminator))) <= 0) return false;
if (nullTerminator == 0x0D)
fieldDescriptorDone = true;
else
::lseek( fd, -1, SEEK_CUR);
}
// ** move to the end of the Header
::lseek( fd, _xBaseHeader._headerLength + 1, SEEK_SET);
// ** reserve AttributeListList
_shapeAttributeListList.reserve(_xBaseHeader._numRecord);
// ** read each record and store them in the ShapeAttributeListList
char record[_xBaseHeader._recordLength];
std::vector<XBaseFieldDescriptor>::iterator it, end = _xBaseFieldDescriptorList.end();
for (Integer i = 0; i < _xBaseHeader._numRecord; ++i)
{
if ((nbytes = ::read( fd, &record, sizeof(record))) <= 0) return false;
char * recordPtr = record;
osgSim::ShapeAttributeList * shapeAttributeList = new osgSim::ShapeAttributeList;
shapeAttributeList->reserve(_xBaseFieldDescriptorList.size());
for (it = _xBaseFieldDescriptorList.begin(); it != end; ++it)
{
switch (it->_fieldType)
{
case 'C':
{
char str[it->_fieldLength + 1];
memcpy(str, recordPtr, it->_fieldLength);
str[it->_fieldLength] = 0;
shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (char*) str));
break;
}
case 'N':
{
char number[it->_fieldLength + 1];
memcpy(number, recordPtr, it->_fieldLength);
number[it->_fieldLength] = 0;
shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (int) atoi(number)));
break;
}
case 'I':
{
int number;
memcpy(&number, record, it->_fieldLength);
shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (int) number));
break;
}
case 'O':
{
double number;
memcpy(&number, record, it->_fieldLength);
shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (double) number));
break;
}
default:
{
osg::notify(osg::WARN) << "ESRIShape::XBaseParser : record type "
<< it->_fieldType << "not supported, skipped" << std::endl;
shapeAttributeList->push_back(osgSim::ShapeAttribute((const char *) it->_name, (double) 0));
break;
}
}
recordPtr += it->_fieldLength;
}
_shapeAttributeListList.push_back(shapeAttributeList);
}
close (fd);
return true;
}
}

View File

@ -0,0 +1,82 @@
#ifndef XBASEPARSER_H_
#define XBASEPARSER_H_
#include <vector>
#include <string>
#include "ESRIType.h"
#include <osg/ref_ptr>
#include <osgSim/ShapeAttribute>
namespace ESRIShape
{
struct XBaseHeader
{
Byte _versionNumber;
Byte _lastUpdate[3];
Integer _numRecord;
Short _headerLength;
Short _recordLength;
Short _reserved;
Byte _incompleteTransaction;
Byte _encryptionFlag;
Integer _freeRecordThread;
Integer _reservedMultiUser[2];
Byte _mdxflag;
Byte _languageDriver;
Short _reserved2;
void print();
bool read(int fd);
};
struct XBaseFieldDescriptor
{
Byte _name[11];
Byte _fieldType;
Integer _fieldDataAddress;
Byte _fieldLength;
Byte _decimalCount;
Short _reservedMultiUser;
Byte _workAreaID;
Short _reservedMultiUser2;
Byte _setFieldFlag;
Byte _reserved[7];
Byte _indexFieldFlag;
void print();
bool read(int fd);
};
class XBaseParser
{
public:
typedef std::vector< osg::ref_ptr<osgSim::ShapeAttributeList> > ShapeAttributeListList;
XBaseParser(const std::string fileName);
~XBaseParser() {}
ShapeAttributeListList & getAttributeList() { return _shapeAttributeListList; }
private:
XBaseParser();
bool parse(int fd);
ShapeAttributeListList _shapeAttributeListList;
bool _valid;
};
}
#endif /*XBASEPARSER_H_*/

View File

@ -28,6 +28,7 @@ SET(LIB_PUBLIC_HEADERS
${HEADER_PATH}/ScalarBar
${HEADER_PATH}/ScalarsToColors
${HEADER_PATH}/Sector
${HEADER_PATH}/ShapeAttribute
${HEADER_PATH}/SphereSegment
${HEADER_PATH}/Version
${HEADER_PATH}/VisibilityGroup
@ -58,6 +59,7 @@ ADD_LIBRARY(${LIB_NAME}
ScalarBar.cpp
ScalarsToColors.cpp
Sector.cpp
ShapeAttribute.cpp
SphereSegment.cpp
Version.cpp
VisibilityGroup.cpp

View File

@ -0,0 +1,129 @@
#include <osgSim/ShapeAttribute>
namespace osgSim
{
ShapeAttribute::ShapeAttribute() :
_type(UNKNOW),
_integer(0)
{}
ShapeAttribute::ShapeAttribute(const char * name) :
_name(name),
_type(UNKNOW),
_integer(0)
{}
ShapeAttribute::ShapeAttribute(const char * name, int value) :
_name(name),
_type(INTEGER),
_integer(value)
{}
ShapeAttribute::ShapeAttribute(const char * name, double value) :
_name(name),
_type(DOUBLE),
_double(value)
{}
ShapeAttribute::ShapeAttribute(const char * name, const char * value) :
_name(name),
_type(STRING)
{
std::string str(value);
_string = new char[str.size() + 1];
memcpy(_string, str.c_str(), str.size());
_string[str.size()] = 0;
}
ShapeAttribute::ShapeAttribute(const ShapeAttribute & sa) :
_name(sa._name),
_type(sa._type)
{
switch (_type)
{
case INTEGER:
{
_integer = sa._integer;
break;
}
case STRING:
{
std::string str(sa._string);
_string = new char[str.size() + 1];
memcpy(_string, str.c_str(), str.size());
_string[str.size()] = 0;
break;
}
case DOUBLE:
{
_double = sa._double;
break;
}
case UNKNOW:
default:
{
_integer = 0;
break;
}
}
}
ShapeAttribute::~ShapeAttribute()
{
if ((_type == STRING) && (_string)) delete [] _string;
}
int ShapeAttribute::compare(const osgSim::ShapeAttribute& sa) const
{
if (_name<sa._name) return -1;
if (sa._name<_name) return 1;
if (_type<sa._type) return -1;
if (sa._type<_type) return 1;
if (_name<sa._name) return -1;
if (sa._name<_name) return 1;
switch (_type)
{
case STRING:
{
if (_string<sa._string) return -1;
if (sa._string<_string) return 1;
}
case DOUBLE:
{
if (_double<sa._double) return -1;
if (sa._double<_double) return 1;
}
case INTEGER:
case UNKNOW:
default:
{
if (_integer<sa._integer) return -1;
if (sa._integer<_integer) return 1;
}
}
return 0;
}
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
int ShapeAttributeList::compare(const osgSim::ShapeAttributeList& sal) const
{
const_iterator salIt, thisIt, thisEnd = end();
int ret;
for (thisIt = begin(), salIt = sal.begin(); thisIt!= thisEnd; ++thisIt, ++salIt)
if ((ret = thisIt->compare(*salIt)) != 0) return ret;
return 0;
}
}