很多时候我们需要在矢量文件中记录一些弧形图形,由于目前OGR中没有支持通过圆心半径等方式来保存矢量图形,所以对于这些矢量图形必须要计算出弧线上的点坐标来进行存储,如果自己按照圆弧的算法来创建这些点确实有些麻烦,OGR中提供了一个叫approximateArcAngles的函数来对圆弧点坐标进行计算,使用起来非常方便,下面是该函数的一个简单说明。函数原型为:
创建一段椭圆弧段。指定一个原点坐标、椭圆的长半轴长度、短半轴长度、旋转角度、起始角度和结束角度来生成一段弧段。参数dfMaxAngleStepSizeDegrees用来指定最大步长,可以使用配置选项OGR_ARC_STEPSIZE来进行设置默认值。生成弧段如图1所示,左侧和下侧两条白色线段分别为X轴和Y轴,交点为坐标原点,绿色椭圆的圆心坐标为(dfCenterX,dfCenterY,dfZ),长半轴和短半轴长度分别如图中两条蓝色线段表示,起始角度和结束角度方向射线如图中紫色线段所示,图中红色的弧段即为生成的弧段。
图1 函数参数说明示意图
OGRGeometry * OGRGeometryFactory::approximateArcAngles( double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees )参数说明:
dfCenterX | 椭圆原点X坐标 |
dfCenterY | 椭圆原点Y坐标 |
dfZ | 椭圆原点Z坐标 |
dfPrimaryRadius | 椭圆长半轴长度 |
dfSecondaryRadius | 椭圆短半轴长度 |
dfRotation | 椭圆顺时针旋转角度 |
dfStartAngle | 弧段起始点角度(与X轴顺时针夹角) |
dfEndAngle | 弧段结束点角度(与X轴顺时针夹角) |
dfMaxAngleStepSizeDegrees | 沿着弧段最长步长对应的角度,设置为0按默认值计算 |
上面创建的是一个线状图层,如果要创建面状图形,需要把里面的线状要素构造一个面状的,上面的代码创建的图形如图2和图3所示。相互垂直的是两个坐标轴X和Y,方便几个弧段定位的,其中有个椭圆,椭圆的圆心为(50,50),长短半轴分别为20和10,同时旋转了45度,生成的弧段范围为整个椭圆弧(0~360),采样间隔为1度,意思就是整个弧段由360个点组成。还有个圆,圆心为(50,-10),半径为10,其他的和椭圆一样。最后还有个半圆弧,半圆弧的圆心为(-50,50),圆半径为20,起点为45度,终点为215度,共180度,一个半圆弧。void WriteVectorFile1() { // 为了支持中文SHP路径,请添加下面这句代码 CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); #ifdef CREATSHP // 为了使属性表字段支持中文,请添加下面这句,创建SHP CPLSetConfigOption("SHAPE_ENCODING", "" ); const char* pszVectorFile = "E:\\TestArc.shp"; const char *pszDriverName = "ESRI Shapefile"; #else // 创建DXF CPLSetConfigOption("GDAL_DATA", "C:\\warmerda\\GDAL110\\data"); const char* pszVectorFile = "E:\\TestArc.dxf"; const char *pszDriverName = "DXF"; #endif // 注册所有的驱动 OGRRegisterAll(); //创建数据 OGRSFDriver *poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName ); if( poDriver == NULL ) { printf( "%s 驱动不可用!\n", pszDriverName ); return; } // 创建数据源 OGRDataSource *poDS = poDriver->CreateDataSource(pszVectorFile, NULL ); if( poDS == NULL ) { printf( "创建矢量文件【%s】失败!\n", pszVectorFile ); return; } // 创建图层,创建一个线图层,这里没有指定空间参考,如果需要的话,需要在这里进行指定 OGRLayer *poLayer = poDS->CreateLayer( "TestPolygon", NULL, wkbLineString, NULL ); if( poLayer == NULL ) { printf( "图层创建失败!\n" ); OGRDataSource::DestroyDataSource( poDS ); return; } // 由于DXF不支持属性表,所以下面几句OGR会提示错误信息 // 下面创建属性表 // 先创建一个叫FieldID的整型属性 OGRFieldDefn oFieldID("FieldID", OFTInteger); poLayer->CreateField(&oFieldID); // 再创建一个叫FeatureName的字符型属性,字符长度为 OGRFieldDefn oFieldName("FieldName", OFTString); oFieldName.SetWidth(100); poLayer->CreateField(&oFieldName); OGRFeatureDefn *poDefn = poLayer->GetLayerDefn(); // 创建两个坐标轴X和Y OGRFeature *poFeatureXAxis = OGRFeature::CreateFeature(poDefn); poFeatureXAxis->SetField(0, 0); poFeatureXAxis->SetField(1, "X轴"); OGRLineString *pGeoXAxis = (OGRLineString*)OGRGeometryFactory::createGeometry(wkbLineString) ; pGeoXAxis->setPoint(0, -100, 0); pGeoXAxis->setPoint(1, 100, 0); poFeatureXAxis->SetGeometry(pGeoXAxis); poLayer->CreateFeature( poFeatureXAxis ); OGRFeature::DestroyFeature( poFeatureXAxis ); // 创建Y轴 OGRFeature *poFeatureYAxis = OGRFeature::CreateFeature(poDefn); poFeatureYAxis->SetField(0, 1); poFeatureYAxis->SetField(1, "Y轴"); OGRLineString *pGeoYAxis = (OGRLineString*) OGRGeometryFactory::createGeometry(wkbLineString) ; pGeoYAxis->setPoint(0, 0, -100); pGeoYAxis->setPoint(1, 0, 100); poFeatureYAxis->SetGeometry(pGeoYAxis); poLayer->CreateFeature( poFeatureYAxis ); OGRFeature::DestroyFeature( poFeatureYAxis ); // 创建圆形要素 OGRFeature *poFeatureCircle = OGRFeature::CreateFeature(poDefn); poFeatureCircle->SetField(0, 2); poFeatureCircle->SetField(1, "圆形"); OGRGeometry * pCircleLine = OGRGeometryFactory::approximateArcAngles(50.0,-10.0, 0.0, 10.0, 10.0, 0.0, 0.0, 360.0, 1.0 ); poFeatureCircle->SetGeometry(pCircleLine); poLayer->CreateFeature( poFeatureCircle ); OGRFeature::DestroyFeature( poFeatureCircle ); // 创建圆形要素 OGRFeature *poFeatureEclipse = OGRFeature::CreateFeature(poDefn); poFeatureEclipse->SetField(0, 3); poFeatureEclipse->SetField(1, "椭圆"); OGRGeometry * pEclipseLine = OGRGeometryFactory::approximateArcAngles(50.0, 50.0, 0.0, 10.0, 20.0, 45.0, 0.0, 360.0, 1.0 ); poFeatureEclipse->SetGeometry(pEclipseLine); poLayer->CreateFeature( poFeatureEclipse ); OGRFeature::DestroyFeature( poFeatureEclipse ); // 创建半圆形要素 OGRFeature *poFeatureArc = OGRFeature::CreateFeature(poDefn); poFeatureArc->SetField(0, 4); poFeatureArc->SetField(1, "半圆形"); OGRGeometry * pArcLine = OGRGeometryFactory::approximateArcAngles(-50.0,50.0, 0.0, 20.0, 20.0, 0.0, 45.0, 215.0, 1.0 ); poFeatureArc->SetGeometry(pArcLine); poLayer->CreateFeature( poFeatureArc ); OGRFeature::DestroyFeature( poFeatureArc ); OGRDataSource::DestroyDataSource( poDS ); printf( "\n数据集创建完成!\n" ); }
图2 创建的Shp图形用ArcMap打开标记属性值
图3 创建的DXF图形用AutoCAD打开