Qt + GDAL 矢量图层操作
前言
这是第四篇文章了,不过其实这篇文章的内容做的要比前面三篇早,主要是中间出现了一个错误,直到最近才解决问题。
参考文档:
OGR API教程:https://www.gdal.org/ogr_apitut.html
GDAL显示线性shp文件:http://www.cnblogs.com/lwngreat/p/4615325.html
C++、GDAL创建shapefile文件:https://blog.csdn.net/ivan_ljf/article/details/9620681
创建写入shp文件流程
显示遥感图像和绘制shp矢量文件都是在Qt里面的GraphicsView控件上进行的,GraphicsView控件包含三层,GraphicsView;GraphicsScene;GraphicsItem;在这里不再赘述。
好,在这里插入一下GDAL的OGR库的结构:
1、 先把点坐标信息存入OGRPoint:
point.setX(Mousepoint.x());
point.setY(Mousepoint.y());
2、 然后将点存入OGRLinearRing:
linestring->addPoint(&point);
3、 然后将OGRLinearRing(线性环)存入OGRPolygen(多边形模型),但这里有个问题,有时候起始点和结束点不是同一个点,所以需要先将环强制闭合,在起始点加入一个点,强制闭合:
linestring->closeRings();
4、 然后存入OGRPolygen:
pogen->addRing(linestring);
//重置OGRLinearRing
linestring->empty();
5、 在向shp文件里写入图形时,需要新建一个OGRFeature向文件里写入,OGRFeature包含一个方法:
pofeature->SetGeometry();
括号中需要一个OGRGeometry类型变量,可以通过将OGRPolygen强制转换为OGRGeometry:
pogeo = (OGRGeometry*)pogen;
最重要的结构已经构建出来了,接下来只需要向shp文件中写入。
错误
之前的错误原因:
鼠标点击创建点的时候最终的信号传到GraphicsScene中,起初我将上面1、2、3、4步中的实现都存在了Scene中,将OGRGeometry传给saveshp类中,然后在运行的时候出现了异常,经过这次修正,我认为是传OGRGeometry时,出现了数据丢失和错误;
修正
修正方法,尽量传值时避免传递外部库的变量,所以我将上面的代码全部整合到saveshp中,然后传值时只传递点击时的点坐标信息(QPoint)
Saveshp.cpp
void saveshp::addPoint(QPointF linepoint)
{
point.setX(linepoint.x());
point.setY(linepoint.y());
linestring->addPoint(&point);
}
void saveshp::endPoint(QPointF linepoint)
{
point.setX(linepoint.x());
point.setY(linepoint.x());
linestring->addPoint(&point);
linestring->closeRings();
pogen->addRing(linestring);
linestring->empty();
}
OGRGeometry *saveshp::creategro()
{
pogeo = (OGRGeometry*)pogen;
return pogeo;
}
void saveshp::savefile()
{
}
void saveshp::insertline(QString filename)
{
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
CPLSetConfigOption("SHAPE_ENCODING","");
//注册所有驱动
GDALAllRegister();
OGRRegisterAll();
GDALDriver *podriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("ESRI Shapefile");
GDALDataset *pods = podriver->Create(filename.toStdString().c_str(),0,0,0,GDT_Unknown,NULL);
if (pods == NULL)
{
return;
}
OGRSpatialReference *pospatialref = new OGRSpatialReference(pods->GetProjectionRef());
OGRLayer *polayer = pods->CreateLayer("vectorline",pospatialref,wkbPolygon,NULL);
if (polayer == NULL)
{
GDALClose(pods);
return;
}
//下面创建属性表
//先创建一个叫FieldID的整型属性
OGRFieldDefn ofid("FieldID",OFTInteger);
polayer->CreateField(&ofid);
//在创建一个叫Feature Name的字符型属性,字符长度为一百
OGRFieldDefn ofname("FieldName",OFTString);
ofname.SetWidth(100);
polayer->CreateField(&ofname);
OGRFeatureDefn *podefn = polayer->GetLayerDefn();
OGRFeature *pofeature = OGRFeature::CreateFeature(podefn);
pofeature->SetField(0,0);
pofeature->SetField(1,"line");
pofeature->SetGeometry(creategro());
polayer->CreateFeature(pofeature);
OGRFeature::DestroyFeature(pofeature);
intline++;
GDALClose(pods);
}