创建存储文件头的头文件 header.h
头中定义header类
class Header {
public:
int FileCode;
int Unused;
int FileLength;
int Version;
int ShapeType;
double Xmin;
double Ymin;
double Xmax;
double Ymax;
double Zmin;
double Zmax;
double Mmin;
double Mmax;
};
创建存储格式的头文件 shape.h
point->line->polygon
先要创建一个point类
class Point { //点
public:
double X;
double Y;
Point() {}
void set_Point(double x, double y)
{
X = x;
Y = y;
}
};
然后根据polygon的属性 创建Shape 类
class Shape
{
public:
int ShapeType;
int RecordNumber;
int ContentLength;
double Box[4];//边界
int NumParts;
int NumPoints;
int* Parts = new int[NumParts];
//以上是记录头,下面是记录的Points
std::vector<Point> Points;//存储所有点的位置
std::vector<PointM> PointMs;
double M_Range[2];
double* M_Array = new double[NumPoints];
};
然后创建Polygon 类继承Shape, 属性已经有了在类中只考虑向属性存储
class PolygonShape :public Shape {//多边
public:
PolygonShape() {}
void set_ShapeType(int a) {
ShapeType = a;
}
void set_NumParts(int a) {
NumParts = a;
}
void set_NumPoints(int a) {
NumPoints = a;
}
void set_Box(double* a) {
memcpy(Box, a, 4 * sizeof(double));
}
void set_Parts(int* a) {
memcpy(this->Parts, a, NumParts * sizeof(int));
}
void set_Points(Point a) {
Points.push_back(a);
}
void set_RecordNumber(int a) {
RecordNumber = a;
}
void set_ContentLength(int a) {
ContentLength = a;
}
void vectorclose() {
Points.clear();
}
};
需要向数据库中写入 创建 database.h 头文件
#include <iostream>
#include <string>
#include <mysql.h>
#include <string>
using namespace std;
MYSQL mysql; //实例MYSQL
MYSQL_FIELD* fd;//字段列数组
char filed[32][100];//存字段名二维数组 可存32个字段
MYSQL_RES* res;//这个结构代表返回行的一个查询结果集合
MYSQL_ROW column;//标识数据行的列
char sql[150];//sql语句
//连接数据库
bool ConnectDatabase() {
mysql_init(&mysql);//初始化mysql
const char host[] = "localhost";
const char username[] = "root";
const char password[] = "7029";
const char databasename[] = "shp";
const int port = 3306;
if (!(mysql_real_connect(&mysql, host, username, password, databasename, port, NULL, 0)))
{cout << "error connect \n";
return false;
}
else {cout << "connect successful\n";
return true;}
}
//释放数据库的连接
void freeconnect() {
mysql_free_result(res); //释放一个结果集合使用的内存
mysql_close(&mysql);//关闭服务器连接
}
//查询
bool QueryDatabase() {
mysql_query(&mysql, "set names gbk");
//执行SQL语句 返回0 查询成功,返回1查询失败
if (mysql_query(&mysql, "select * from header"))
{ printf("Query failed (%s)\n", mysql_error(&mysql));
return false;}
else
{ printf("query success\n");
}
//MYSQL_RES* res 存储行的查询结果
res = mysql_store_result(&mysql);
//打印数据行数
printf("number of dataline returned: %d\n", mysql_affected_rows(&mysql));
for (int i = 0; fd = mysql_fetch_field(res); i++) //从结果中取得每一个字段存入fd中
{strcpy(field[i], fd->name);}
int j = mysql_num_fields(res); // 获取列数
for (int i = 0; i < j; i++) //打印字段
{printf("%10s\n", field[i]);}
while (column = mysql_fetch_row(res))
{for (int i = 0; i < j; i++)
printf("%10s\t", column[i]);
printf("\n");}
return true;
}
//创建表涉及到3个表 头文件,记录头,记录
bool create_table() {
string str0 = "create table header_data(FileCode int , FileLength int ,Version int ,ShapeType int );";
string str1 = "create table record_header_data(RecordNumber int primary key , ContentLength int ,ShapeType int ,NumParts int ,NumPoints int);"; //可将RecordNumber作主键标识
string str2 = "create table point_record_data(X double ,Y double ,RecordNumber int );";//可将RecordNumber作为此表的外键标识
mysql_query(&mysql, str0.c_str());
mysql_query(&mysql, str1.c_str());
mysql_query(&mysql, str2.c_str());
return 1;
}
//向头文件表插入数据
bool insert_header_data(int FileCode, int FileLength, int Version, int ShapeType, double xmin, double ymin, double xmax, double ymax ) {
string str;
str = "insert into header_data values(";
str += to_string(FileCode);
str += ",";
str += to_string(FileLength);
str += ",";
str += to_string(Version);
str += ",";
str += to_string(ShapeType);
str += ",";
str += to_string(xmin);
str += ",";
str += to_string(ymin);
str += ",";
str += to_string(xmax);
str += ",";
str += to_string(ymax);
str += ");";
cout << str;
if (mysql_query(&mysql, str.c_str()))//执行sql语句
{ cout << "insert error";
return false;}
else { cout << "insert successful";
return true;
}
}
//向记录头表插入数据
bool insert_recordheader_data(int RecordNumber, int ContentLength, int ShapeType, int NumParts,int NumPoints ) {
string str;
str = "insert into record_header_data values(";
str += to_string(RecordNumber);
str += ",";
str += to_string(ContentLength);
str += ",";
str += to_string(ShapeType);
str += ",";
str += to_string(NumParts);
str += ",";
str += to_string(NumPoints);
str += ");";
cout << str;
if (mysql_query(&mysql, str.c_str()))//执行sql语句
{ cout << "insert error";
return false;}
else { cout << "insert successful";
return true;}
}
//向记录表插入数据
bool insert_pointrecord_data(double x,double y ,int record ) {
string str;
str = "insert into point_record_data values(";
str += to_string(x);
str += ",";
str += to_string(y);
str += ",";
str += to_string(record);
str += ");";
cout << str;
if (mysql_query(&mysql, str.c_str()))//执行sql语句
{ cout << "insert error\n";
return false;}
else {
cout << "insert successful\n";
return true;
}
}
然后主函数include 头文件 对.shp进行读取和写入
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "shape.h"
#include "header.h"
#include"database.h"
using namespace std;
PolygonShape abc;//实例PolygonShape
Header header;//实例 header
std::vector<PolygonShape> polygon;//创建存储polygon的vector容器
//BT函数用来地址大小端的转换
template<class T>
T BT(T m)
{
//union联合体内所有的数据公用一个内存
union n_
{
T n;
char mem[sizeof(T)];
};
n_ big, smal;
big.n = m;
for (int i = 0; i < sizeof(T); i++)
{
smal.mem[i] = big.mem[sizeof(T) - i - 1];//低位和高位转换
}
return smal.n;
}
//定义一个读取文件头的函数
void ReadFileHeard(FILE * ShpFile_fp) {
// 读取坐标文件头的内容开始
int Unused;
fread(&header.FileCode, sizeof(int), 1, ShpFile_fp);
header.FileCode = BT(header.FileCode);//FileCode为大端
printf("FileCode=%d\n", header.FileCode);
for (int i = 0;i < 5;i++)//根据格式 有五个空的int
fread(&Unused, sizeof(int), 1, ShpFile_fp);
//5个过后读取文件长度
fread(&header.FileLength, sizeof(int), 1, ShpFile_fp);
header.FileLength = BT(header.FileLength);
printf("FileLength=%d\n", header.FileLength);
fread(&header.Version, sizeof(int), 1, ShpFile_fp);//读取Version
printf("Version=%d\n", header.Version);
fread(&header.ShapeType, sizeof(int), 1, ShpFile_fp);//读取ShapeType
printf("ShapeType=%d\n", header.ShapeType);
//文件头格式依次读取
fread(&header.Xmin, sizeof(double), 1, ShpFile_fp);
fread(&header.Ymin, sizeof(double), 1, ShpFile_fp);
fread(&header.Xmax, sizeof(double), 1, ShpFile_fp);
fread(&header.Ymax, sizeof(double), 1, ShpFile_fp);
fread(&header.Zmin, sizeof(double), 1, ShpFile_fp);
fread(&header.Zmax, sizeof(double), 1, ShpFile_fp);
fread(&header.Mmin, sizeof(double), 1, ShpFile_fp);
fread(&header.Mmax, sizeof(double), 1, ShpFile_fp);
//打印
printf("Xmin=%lf\n", header.Xmin);
printf("Ymin=%lf\n", header.Ymin);
printf("Xmax=%lf\n", header.Xmax);
printf("Ymax=%lf\n", header.Ymax);
printf("Zmin=%lf\n", header.Zmin);
printf("Zmin=%lf\n", header.Zmax);
printf("Mmax=%lf\n", header.Mmin);
printf("Mmax=%lf\n", header.Mmax);
}
//定义一个读取记录的函数
void OnReadPolygonShp(FILE* ShpFile)
{ Point point;//先定义一个 Point类型的实例用于保存点
int i, j;
int RecordNumber;
int ContentLength;
int shapeType;
double Box[4];
int NumParts;
int NumPoints;
int *Parts;
while ((fread(&RecordNumber, sizeof(int), 1, ShpFile) != 0))
{ RecordNumber = BT(RecordNumber);//RecordNumber为大端需要BT转换
abc.set_RecordNumber(RecordNumber);//存入实例中
fread(&ContentLength, sizeof(int), 1, ShpFile);//按序读取
ContentLength = BT(ContentLength);
abc.set_ContentLength(ContentLength);
fread(&shapeType, sizeof(int), 1, ShpFile);
abc.set_ShapeType(shapeType);
for (i = 0;i < 4;i++)
{fread(Box + i, sizeof(double), 1, ShpFile);//范围
}
abc.set_Box(Box);
fread(&NumParts, sizeof(int), 1, ShpFile);
abc.set_NumParts(NumParts);
Parts = new int[abc.NumParts];
fread(&NumPoints, sizeof(int), 1, ShpFile);
abc.set_NumPoints(NumPoints);
for (i = 0;i < abc.NumParts;i++)//根据Part的个数记录
{fread(&Parts[i], sizeof(int), 1, ShpFile);//部分的 开始点的索引
}
abc.set_Parts(Parts);
int pointNum;//用来存储计算点个数
for (i = 0;i < NumParts;i++)
{ if (i != NumParts - 1)//如果不是倒数第二个
pointNum = Parts[i + 1] - Parts[i];//用下一个Parts的地址 减去上一个地址 得出的就是点的地址个数
else
pointNum = NumPoints - Parts[i];
double PointsX;
double PointsY;
for (j = 0;j < pointNum;j++)
{ fread(&PointsX, sizeof(double), 1, ShpFile);
fread(&PointsY, sizeof(double), 1, ShpFile);
point.set_Point(PointsX, PointsY);//point属性赋值
abc.set_Points(point);//对polygon属性赋值
}
}
//一端段记录读取结束将添加到polygon容器中
polygon.push_back(abc);
//对polygon属性中的PO
abc.vectorclose();
}
}
//读取的值写入txt文本
void write(string filepath) {
ofstream file;
file.open(filepath, ios::out);
file << "FileCode" ;
file <<std::to_string(header.FileCode);//转换成字符串写入
file<<"\n";
file << "FileLength:";
file << std::to_string(header.FileLength);
file << "\n";
file << "Version:";
file << std::to_string(header.Version);
file << "\n";
file << "ShapeType:";
file << std::to_string(header.ShapeType);
file << "\n";
file << "Xmin:";
file << std::to_string(header.Xmin);
file << "\n";
file << "Ymin:";
file << std::to_string(header.Ymin);
file << "\n";
file << "Xmax:";
file << std::to_string(header.Xmax);
file << "\n";
file << "Ymax:";
file << std::to_string(header.Ymax);
file << "\n";
file << "Zmin:";
file << std::to_string(header.Zmin);
file << "\n";
file << "Zmax:";
file << std::to_string(header.Zmax);
file << "\n";
file << "Mmin:";
file << std::to_string(header.Mmin);
file << "\n";
file << "Mmax:";
file << std::to_string(header.Mmax);
file << "\n";
//遍历polygon容器vector
for (int i = 0;i < polygon.size();i++)
{ file << "RecordNumber:";
file << std::to_string(polygon[i].RecordNumber);
file << "\n";
file << "ContentLength:";
file << std::to_string(polygon[i].ContentLength);
file << "\n";
file << "ShapeType:";
file << std::to_string(polygon[i].ShapeType);
file << "\n";
file << "NumParts:";
file << std::to_string(polygon[i].NumParts);
file << "\n";
file << "NumPoints:";
file << std::to_string(polygon[i].NumPoints);
file << "\n";
//遍历第i个ploygon的Point点 也可以 j<polygon.NumPoints
for (int j=0;j < polygon[i].Points.size();j++)
{ file<< "X:";
cout << polygon[i].Points[j].X ;
std::to_string(polygon[i].Points[j].X);
file << std::to_string(polygon[i].Points[j].X);
file << " Y:";
cout << polygon[i].Points[j].Y << "\n";
file << std::to_string(polygon[i].Points[j].Y);
file << '\n';
}
}
}
//将读取的数据存入新的.shp
void writetoshp(string filepathh) {
int zero =0;
ofstream file;
file.open(filepathh, ios::binary | ios::out);
//将头文件的参数定义出来,并对大小端转换
int code = BT(header.FileCode);
int length = BT(header.FileLength);
int version = BT(header.Version);
int recordnumber;
int contentlength;
int shapetype;
file.write((const char*)& code, sizeof(int));
//5个unused
for (int i = 0;i < 5;i++) {
file.write((const char*)& zero, sizeof(int));
}
file.write((const char*)& length, sizeof(int));
file.write((const char*)& header.Version, sizeof(int));
file.write((const char*)& header.ShapeType, sizeof(int));
file.write((const char*)& header.Xmin, sizeof(double));
file.write((const char*)& header.Ymin, sizeof(double));
file.write((const char*)& header.Xmax, sizeof(double));
file.write((const char*)& header.Ymax, sizeof(double));
file.write((const char*)& header.Zmin, sizeof(double));
file.write((const char*)& header.Zmax, sizeof(double));
file.write((const char*)& header.Mmin, sizeof(double));
file.write((const char*)& header.Mmax, sizeof(double));
//和写入txt步骤相同
for (int i = 0;i < polygon.size();i++)
{ recordnumber = BT(polygon[i].RecordNumber);
contentlength = BT(polygon[i].ContentLength);
file.write((const char*)& recordnumber, sizeof(int));
file.write((const char*)& contentlength, sizeof(int));
file.write((const char*)& polygon[i].ShapeType, sizeof(int));
for (int j = 0;j < 4;j++)
{
file.write((const char*)& polygon[i].Box[j], sizeof(double));
}
file.write((const char*)& polygon[i].NumParts, sizeof(int));
file.write((const char*)& polygon[i].NumPoints, sizeof(int));
for (int j = 0;j < polygon[i].NumParts;j++)
{ file.write((const char*)& polygon[i].Parts[j], sizeof(int));
}
for (int j = 0;j < polygon[i].NumPoints;j++)
{ file.write((const char*)& polygon[i].Points[j].X, sizeof(double));
file.write((const char*)& polygon[i].Points[j].Y, sizeof(double));
}
}
}
void main() {
FILE* ShpFile_fp;
fopen_s(&ShpFile_fp, "C:\\Users\\shitk\\Desktop\\ExtBkArea.shp", "rb");
string file2path = "C:\\Users\\shitk\\Desktop\\new.shp";
string filepath = "C:\\Users\\shitk\\Desktop\\polygon.txt";
ReadFileHeard(ShpFile_fp);
OnReadLineShp(ShpFile_fp);
write(filepath);
writetoshp(file2path);
ConnectDatabase();
create_table();
//insert_header_data(header.FileCode, header.FileLength, header.Version, header.ShapeType,header.Xmin,header.Ymin,header.Xmax,header.Ymax);
//QueryDatabase();
insert_header_data(header.FileCode, header.FileLength, header.Version, header.ShapeType, header.Xmin, header.Ymin, header.Xmax, header.Ymax);
for (int i = 0;i < polygon.size();i++)
{ insert_recordheader_data(polygon[i].RecordNumber, polygon[i].ContentLength, polygon[i].ShapeType, polygon[i].NumParts, polygon[i].NumPoints);
for (int j = 0;j < polygon[i].Points.size();j++)
{
insert_pointrecord_data(polygon[i].Points[j].X, polygon[i].Points[j].Y, polygon[i].RecordNumber);
}
}
}
}