AutoCAD中有三种方法可以画圆:“圆心、半径”法画圆、“两点”法画圆、“三点”法画圆。下面采用这三种方法,使用ObjectARX在AutoCAD2002中画圆。
1)使用ObjectARX向导创建一个项目,名称为CreateEnt4,勾选使用“Use MFC”。如下图所示:
图(1)勾选“Use MFC”
2)选择【Insert/New Class】菜单项,系统会弹出如图2.8所示的对话框。输入CCreateEnt作为新类的名称,单击【OK】按钮创建新类。使用同样的方法,创建一个名为CmodifyEnt的类。如下图所示:
图(2)添加一个类CCreateEnt,类CmodifyEnt也是一样。
3)在CCreateEnt 和CModifyEnt 类的头文件中,分别添加包含头文件的语句:
#include "StdArx.h"
然后在StdArx.h 文件中,添加下面的包含语句:
#include "dbents.h"
如图(3)、图(4)所示:
图(3)在CreateEnt.h中添加对StdArx.h的引用,同理,在ModifyEnt.h中也要添加对StdArx.h的引用
图(4)在StdArx.h中添加对dbents.h的引用
4)2)在CCreateEnt 类中,添加一个新的函数CreateCircle,该函数直接封装AcDbCircle类的构造函数,其声明和实现分别为:
//声明部分在CreateEnt.h文件中
static AcDbObjectId CreateCircle(AcGePoint3d ptCenter,
AcGeVector3d vec,double radius);
//实现部分在CreateEnt.cpp文件中
//添加一个圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint3d ptCenter, AcGeVector3d vec,double radius)
{
AcDbCircle *pCircle=new AcDbCircle(ptCenter,vec,radius);
//将实体添加到图形数据库中
AcDbObjectId circleId;
circleId=CCreateEnt::PostToModelSpace(pCircle);
return circleId;
}
5)在CCreateEnt 类中,再添加一个新的函数CreateCircle(这就使用了函数重载的概念),用于创建位于XOY 平面上的圆(一般创建的二维图形都是在XOY 平面上),其声明和实现分别为:
//声明部分
static AcDbObjectId CreateCircle(AcGePoint3d ptCenter,double radius);
//实现部分
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint3d ptCenter,double radius)
{
AcGeVector3d vec(0,0,1);
return CCreateEnt::CreateCircle(ptCenter,vec,radius);
}
代码相当简单,区别就在于输入了一个代表XOY 平面的法向矢量。
6)在项目中添加一个新类CCalculation,用于封装计算的相关函数。添加两个重载静态函数MiddlePoint,用于计算两点连线的中点:
//计算直线的中点
AcGePoint2d CCalculation::MiddlePoint(AcGePoint2d pt1,AcGePoint2d pt2)
{
AcGePoint2d pt;
pt[X]=(pt1[X]+pt2[X])/2; //X、Y都要大写
pt[Y]=(pt1[Y]+pt2[Y])/2;
//创建圆
return pt;
}
AcGePoint3d CCalculation::MiddlePoint(AcGePoint3d pt1,AcGePoint3d pt2)
{
AcGePoint3d pt;
pt[X]=(pt1[X]+pt2[X])/2;
pt[Y]=(pt1[Y]+pt2[Y])/2;
pt[Z]=(pt1[Z]+pt2[Z])/2;
return pt;
}
7)在CCreateEnt 类中,添加一个两点法创建圆的函数:
//用两点画圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2)
{
//计算圆心和半径
AcGePoint2d pt=CCalculation::MiddlePoint(pt1,pt2);
AcGePoint3d ptCenter(pt[X],pt[Y],0);//圆心
double radius=pt1.distanceTo(pt2)/2;
//创建圆
return CCreateEnt::CreateCircle(ptCenter,radius);
}
上面的代码中,调用CCalculation::MiddlePoint 函数来获得两点连线的中点,也就是圆心;
AcGePoint2d::distanceTo 函数用于计算两点之间的距离。
8)使用几何类来实现三点法画圆的函数。在ObjectARX 中提供了一个以AcGe 开头的类库(一般称为几何类),用来完成一些计算工作,关于几何类会在详细介绍,这里使用了AcGeCircArc3d 类来完整需要的工作。这里需要引入两个头文件:#include "gearc3d.h" 和 #include "gearc2d.h"
//三点画圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2, AcGePoint2d pt3)
{
//使用几何类
AcGeCircArc2d geArc(pt1,pt2,pt3);
AcGePoint3d ptCenter(geArc.center().x,geArc.center().y,0);
return CCreateEnt::CreateCircle(ptCenter,geArc.radius());
}
AcGeCircArc2d 类能够创建一个几何类的圆弧对象,该对象仅用来计算,不能在图形窗口中显示。AcGeCircArc2d 类有四个构造函数,其中一个构造函数可以根据三个点创建圆弧,这里正是使用该函数创建了几何类的圆弧。
构建几何类的圆弧之后,就可以查询该对象的圆心、所在平面、半径等特性,将这些参数传递到创建圆的函数中,就可以实现三点法创建圆。
9)在项目中注册一个新命令AddCircle,对几个创建圆的函数进行测试,该命令的实现函数为:
// This is command 'ADDCIRCLE'
void WhCHAP2ADDCIRCLE()
{
// TODO: Implement the command
//"圆心、半径"方法画圆
AcGePoint3d ptCenter(100,100,0);
CCreateEnt::CreateCircle(ptCenter,20);
//两点法画圆
AcGePoint2d pt1(70,100);
AcGePoint2d pt2(130,100);
CCreateEnt::CreateCircle(pt1,pt2);
//三点法画圆
pt1.set(60,100);
pt2.set(140,100);
AcGePoint2d pt3(100,60);
CCreateEnt::CreateCircle(pt1,pt2,pt3);
}
注意:在CreateEnt.h要引用两个头文件:#include "gearc3d.h" 和 #include "gearc2d.h",在XXXCommand.cpp要引用如下5个头文件:
图(5)在在XXXCommand.cpp要引用5个头文件
10)编译并运行该程序,在AutoCAD 2002 中运行AddCircle命令,就能得到如图(6)所示的效果:
图(8)三种画圆的效果
附录:
//CreateEnt.h
#include "StdArx.h"
#include "gearc2d.h"
#include "gearc3d.h"
class CCreateEnt
{
public:
CCreateEnt();
virtual ~CCreateEnt();
static AcDbObjectId PostToModelSpace(AcDbEntity* pEnt);
static AcDbObjectId CreateCircle(AcGePoint3d ptCenter,
AcGeVector3d vec,double radius);
static AcDbObjectId CreateCircle(AcGePoint3d ptCenter,double radius);
static AcDbObjectId CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2);
static AcDbObjectId CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2,
AcGePoint2d pt3);
};
//CreateEnt.cpp
#include "stdafx.h"
#include "resource.h"
#include "CreateEnt.h"
#include "Calculation.h"
#include "gearc2d.h"
#include "gearc3d.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
CCreateEnt::CCreateEnt()
{
}
CCreateEnt::~CCreateEnt()
{
}
//将实体添加到图形数据库的模型空间
AcDbObjectId CCreateEnt::PostToModelSpace(AcDbEntity* pEnt)
{
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable,AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord,
AcDb::kForWrite);
AcDbObjectId entId;
pBlockTableRecord->appendAcDbEntity(entId,pEnt);
pBlockTable->close();
pBlockTableRecord->close();
pEnt->close();
return entId;
}
//添加一个圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint3d ptCenter, AcGeVector3d vec,double radius)
{
AcDbCircle *pCircle=new AcDbCircle(ptCenter,vec,radius);
//将实体添加到图形数据库中
AcDbObjectId circleId;
circleId=CCreateEnt::PostToModelSpace(pCircle);
return circleId;
}
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint3d ptCenter,double radius)
{
AcGeVector3d vec(0,0,1);
return CCreateEnt::CreateCircle(ptCenter,vec,radius);
}
//用两点法画圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2)
{
//计算圆心和半径
AcGePoint2d pt=CCalculation::MiddlePoint(pt1,pt2);
AcGePoint3d ptCenter(pt[X],pt[Y],0);//圆心
double radius=pt1.distanceTo(pt2)/2; //半径等于pt1、pt2两点距离的一半
//创建圆
return CCreateEnt::CreateCircle(ptCenter,radius);
}
//用三点法画圆
AcDbObjectId CCreateEnt::CreateCircle(AcGePoint2d pt1,AcGePoint2d pt2, AcGePoint2d pt3)
{
//使用几何类
AcGeCircArc2d geArc(pt1,pt2,pt3);
AcGePoint3d ptCenter(geArc.center().x,geArc.center().y,0);
return CCreateEnt::CreateCircle(ptCenter,geArc.radius());
}