利用ShapeLib读写ShapeFile文件

最近在做GIS相关的项目,遇到读写shapefile文件的需求,根据ShapeLib开源库定义的接口,编写了读shapefile和写shapefile的两个样例程序,仅供参考学习。

1.定义坐标点数据类型

struct Point
{
	Point()
	{
	    x = 0.0;
	    y = 0.0;
	    z = 0.0;
	}

	Point(double _x, double _y, double _z)
	{
	    x = _x;
	    y = _y;
	    z = _z;
	}

	double x;
	double y;
	double z;
};

2.读取一个shapefile文件

void readShapeFile()
{
	// 获取shp文件名
	std::string shp_fn = "line.shp";

	SHPHandle hSHP;
	DBFHandle hDBF;
	int nShapeType, nEntities;
	double adfMinBound[4], adfMaxBound[4];

	hSHP = SHPOpen(shp_fn.c_str(), "r");
	if (hSHP == NULL)
	{
		return;
	}

	char szDBF[MAX_PATH + 1];

	strcpy_s(szDBF, shp_fn.c_str());
	szDBF[strlen(szDBF) - 3] = '\0';
	strcat_s(szDBF, "dbf");
	hDBF = DBFOpen(szDBF, "rb");
	if (!hDBF)
	{
		SHPClose(hSHP);
		return;
	}

	SHPGetInfo(hSHP, &nEntities, &nShapeType, adfMinBound, adfMaxBound);

	SHPObject *psElem;
	double *padfX, *padfY, *padfZ;

	int nField;
	nField = DBFGetFieldCount(hDBF);

	for (int i = 0; i < nEntities; i++)
	{
	    std::vector<Point> shapePoints;

		psElem = SHPReadObject(hSHP, i);

		padfX = new double[psElem->nVertices];
		padfY = new double[psElem->nVertices];
		padfZ = new double[psElem->nVertices];
		for (int j = 0; j < psElem->nVertices; j++)
		{
			padfX[j] = psElem->padfX[j];
			padfY[j] = psElem->padfY[j];
			padfZ[j] = psElem->padfZ[j];

			Point point(padfX[j], padfY[j], padfZ[j]);
			shapePoints.push_back(point);
		}

		for (int j = 0; j < nField; j++)
		{
			DBFFieldType eType;
			int nWidth, nDecimals;
			char szTitle[20];

			eType = DBFGetFieldInfo(hDBF, j, szTitle, &nWidth, &nDecimals);
			switch (eType)
			{
			case FTString:
			{
				std::string value = DBFReadStringAttribute(hDBF, i, j);
			}
			break;
			case FTInteger:
			{
				int value = DBFReadIntegerAttribute(hDBF, i, j);
			}
			break;
			case FTDouble:
			{
				double value = DBFReadDoubleAttribute(hDBF, i, j);
			}
			break;
			default:
				break;
			}
		}

		delete[] padfX;
		delete[] padfY;
		delete[] padfZ;
		SHPDestroyObject(psElem);
	}

	// 关闭文件
	SHPClose(hSHP);
	DBFClose(hDBF);
}

3.写一个shapefile文件

void writeShapeFile()
{
    // 获取shp文件名
    std::string shp_fn = "line";
    // 创建对应的.shp文件和.dbf文件
    SHPHandle hShp = SHPCreate(string(shp_fn + ".shp").c_str(), SHPT_ARCZ);
    DBFHandle hDbf = DBFCreate(string(shp_fn + ".dbf").c_str());

    // 创建dbf文件表
    DBFAddField(hDbf, "ID", FTInteger, 10, 0);
    DBFAddField(hDbf, "Name", FTString, 10, 0);
    DBFAddField(hDbf, "Length", FTDouble, 32, 0);

    // dbf的记录数
    int record_idx = DBFGetRecordCount(hDbf);

    std::vector<Point> line_shp;
    line_shp.push_back(Point(1.0, 2.0, 3.0));
    line_shp.push_back(Point(1.5, 2.6, 3.9));

    int nVertices = line_shp.size();
    if (0 == nVertices)
    {
        return;
    }

    double* padfX = new double[nVertices];
    double* padfY = new double[nVertices];
    double* padfZ = new double[nVertices];

    for (int i = 0; i < nVertices; ++i)
    {
        padfX[i] = line_shp.at(i).x;
        padfY[i] = line_shp.at(i).y;
        padfZ[i] = line_shp.at(i).z;
    }

    SHPObject* shpObject = SHPCreateObject(SHPT_ARCZ, -1, 0, NULL, NULL, nVertices, padfX, padfY, padfZ, NULL);
    SHPWriteObject(hShp, -1, shpObject);
    SHPDestroyObject(shpObject);

    delete[] padfX;
    delete[] padfY;
    delete[] padfZ;

    // 字段索引
    int field_idx = 0;

    DBFWriteIntegerAttribute(hDbf, record_idx, field_idx++, 1001);
    DBFWriteStringAttribute(hDbf, record_idx, field_idx++, "polyline");
    DBFWriteDoubleAttribute(hDbf, record_idx, field_idx++, 10.15);

    DBFClose(hDbf);
    SHPClose(hShp);
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值