使用OGR创建弧形图形

很多时候我们需要在矢量文件中记录一些弧形图形,由于目前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按默认值计算

       通过上面的函数参数说明和图形大概应该就比较清楚了,下面使用一段代码来创建几个图形测试一下。测试代码如下:

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和图3所示。相互垂直的是两个坐标轴X和Y,方便几个弧段定位的,其中有个椭圆,椭圆的圆心为(50,50),长短半轴分别为20和10,同时旋转了45度,生成的弧段范围为整个椭圆弧(0~360),采样间隔为1度,意思就是整个弧段由360个点组成。还有个圆,圆心为(50,-10),半径为10,其他的和椭圆一样。最后还有个半圆弧,半圆弧的圆心为(-50,50),圆半径为20,起点为45度,终点为215度,共180度,一个半圆弧。

图2 创建的Shp图形用ArcMap打开标记属性值

图3 创建的DXF图形用AutoCAD打开

posted on 2013-06-02 13:47  王大王  阅读(576)  评论(0编辑  收藏  举报

导航