转自:http://www.cprogramto.com/get-minimum-bounding-box-of-shapefile-c-program/
这是一个获取shapefile图形最小包围盒的c++程序。这个程序不仅读取了shapefile,还然你明白如何读取其他文件。例如.dbf, .exe, .png等。在此之前你应该了解位、字节顺序以及字节向其他数据类型转换并且更为重要的是你要读取的文件的格式。
一个shapefile存储了非拓扑几何图形。ESRI shapfile主要包含3 个文件,即,shp, .shx 和.dbf文件。为了获取文件中记录的图形的最小包围盒我们要考虑shp的格式。具体参看ESRI Shapefile的技术文档。 .shp 有3个部分,即文件头、记录的头、记录的内容。文件头保存了最小包围盒的内容。你可以用C++程序去读取文件头,以下是实现代码:
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <cstdint>
using namespace std;
class ByteConverter
{
public:
//以BigEndian格式存储的32个位域转换为正数。需要位操作运算支持,例如:左移和按位或操作
static int32_t bigEndianIntRead(char *fileBuf, int startIndex)
{
return (((fileBuf[startIndex+0]&0xff)<<24)|
((fileBuf[startIndex+1]&0xff)<<16)|
((fileBuf[startIndex+2]&0xff)<<8)|
((fileBuf[startIndex+3]&0xff)));
}
// 以BigEndian格式存储的32位数值转换为整型。
static int32_t littleEndianIntRead(char *fileBuf, int startIndex)
{
return (((fileBuf[startIndex+3]&0xff)<<24)|
((fileBuf[startIndex+2]&0xff)<<16)|
((fileBuf[startIndex+1]&0xff)<<8)|
((fileBuf[startIndex+0]&0xff)));
}
// 以BigEndian格式存储的64位或8个字节转换为整型
static double littleEndianDoubleRead(char *fileBuf, int startIndex)
{
double convert;
char *add;
int j;
add = new char();
j=-1;
for (int i=startIndex; i<startIndex+8; i++)
{
j++;
add[j] = fileBuf[i];
}
convert = *reinterpret_cast<double *const>(add);
return convert;
}
};
// shapefile 头文件类,实现了描述shapefile头部所有字段的函数
class HeaderShapefile
{
public:
// 该类的函数将计算出shapefile众包围框的坐标
// 如x和y、最小和最大值同样z和m的最大最小值也可以获取
static double dimensionXmin(char *fileBuf, int startIndex)
{
return ByteConverter::littleEndianDoubleRead(fileBuf,startIndex);
}
static double dimensionYmin(char*fileBuf, int startIndex)
{
return ByteConverter::littleEndianDoubleRead(fileBuf, startIndex);
}
static double dimensionXmax(char*fileBuf, int startIndex)
{
return ByteConverter::littleEndianDoubleRead(fileBuf, startIndex);
}
static double dimensionYmax(char*fileBuf, int startIndex)
{
return ByteConverter::littleEndianDoubleRead(fileBuf, startIndex);
}
};
class SizeOfFile
{
public:
// 确定文件的大小
static long sizeOfFile(FILE *file)
{
long a,b;
a = ftell(file);
fseek(file, 0, 2);
b = ftell(file);
//fseek(file, 1, 0);//字母l被错看成数字1了
fseek(file, a, 0);
}
};
int main()
{
int32_t filecodes, fileLength,shapeTypes,versions;
double xmin,ymin,xmax,ymax,mmin,mmax,zmin,zmax;
string shape;
char *filePath = "文件所在目录";
char *fileBuf;
FILE *file = NULL;
//rb模式打开,这样还可以测试一下文件是否存在或被读取
if ((file=fopen(filePath,"rb"))==NULL)
{
cout <<"无法打开指定文件"<<endl;
}
else
cout <<"成功打开指定文件"<<endl;
// 获取文件大小
long fileSize = SizeOfFile::sizeOfFile(file);
// 为整个文件分配内存
fileBuf = new char[fileSize];
//将文件读取到缓存中
fread(fileBuf, fileSize, 1, file);
//查看二进制文件的信息
cout<< "文件大小:"<< fileSize;
xmin = HeaderShapefile::dimensionXmin(fileBuf,36);
ymin = HeaderShapefile::dimensionYmin(fileBuf,44);
xmax = HeaderShapefile::dimensionXmax(fileBuf,52);
ymax = HeaderShapefile::dimensionYmax(fileBuf,60);
cout<<"\n\n/*************\
shapefile的最新包围盒***********/\n\n";
cout<<"X最小值="<<xmin<<endl;
cout<<"Y最小值="<<ymin<<endl;
cout<<"X最大值="<<xmax<<endl;
cout<<"Y最大值="<<ymax<<endl;
cin.get();
delete []fileBuf;
fclose(file);// 不要忘记
return 0;
//char keep_window_open = getchar();
}
程序的输出结果如下: