【CAD二次开发】-ObjectARX-JIG基本的拖动 BasicJig
(1)使用ObjectARX向导创建一个新项目,命名为BasicJig
developer symble随意填写:
选择:使用MFC共享DLL
必须使用MFC,否则后面会出现编译错误:
fatal error C1189: #error: WINDOWS.H already included. MFC apps must not #include <windows.h>
(2)向工程中添加一个普通新类CDrawSquareJig,将它的父类修改为AcEdJig
然后为类添加几个函数头:
class CDrawSquareJig :
public AcEdJig
{
public:
CDrawSquareJig();
virtual ~CDrawSquareJig();
//外部调用的函数,一般用于Jig的初始化
bool doIt(const AcGePoint3d ¢erPoint,AcDbObjectId& polyId);
//此函数将被drag函数调用以获得用户输入
virtual AcEdJig::DragStatus sampler();
//对需要在拖动过程中发生变化的实体进行修改
virtual Adesk::Boolean update();
//指定了Jig所操作的对象
virtual AcDbEntity* entity() const;
}
(3)添加三个私有的成员变量
private:
AcDbPolyline* m_pPoly; //拖动过程中动态变化的实体
AcGePoint3d m_curPoint; //储存用户光标移动时临时点的临时位置
AcGePoint3d m_centerPoint; //正方形的中心点
(4)在CDrawSquareJig类的构造函数中,需要对指针类型的成员变量进行初始化:
CDrawSquareJig::CDrawSquareJig()
{
m_pPoly = NULL;
}
(5)添加doIt函数的实现代码:
bool CDrawSquareJig::doIt(const AcGePoint3d ¢erPoint,
AcDbObjectId &polyId)
{
m_centerPoint = centerPoint;
//拖动之前:将多段线创建出来
m_pPoly = new AcDbPolyline();
for (int i = 0; i < 4; i++) //将四个顶点连接,形成一个矩形
{
m_pPoly->addVertexAt(i, ToPoint2d(m_centerPoint));
}
m_pPoly->setClosed(Adesk::kTrue); //闭合顶点
//进入拖动流程
CString prompt = TEXT("\n指定标注插入点:");
setDispPrompt(prompt); //使用一种dispPrompt 的拷贝作为后续的拖拽操作的新提示字符串。
AcEdJig::DragStatus stat = drag();
//拖动结束:函数返回部分
if (stat == kNormal)
{
polyId = PostToModelSpace(m_pPoly);
return true;
}
else
{
delete m_pPoly;
return false;
}
}
①注意:使用 CString,
CString prompt = TEXT("\n指定标注插入点:");
需要使用MFC,否则会出现下面的编译错误:
fatal error C1189: #error: WINDOWS.H already included. MFC apps must not #include <windows.h>
②其中,ToPoint2d函数的实现:
AcGePoint2d CDrawSquareJig::ToPoint2d(const AcGePoint3d &point3d)
{
return AcGePoint2d(point3d.x, point3d.y);
}
③其中,PostToModelSpace函数的实现:
AcDbObjectId CDwgDatabaseUtil::PostToModelSpace( AcDbEntity *pEnt, AcDbDatabase *pDb )
{
// 检查输入参数的有效性
assert (pEnt); // 等效于assert (pEnt != NULL);
// 获得当前图形数据库的块表
AcDbBlockTable *pBlkTbl = NULL;
pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
// 获得模型空间对应的块表记录
AcDbBlockTableRecord *pBlkTblRcd = NULL;
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
pBlkTbl->close();
// 将实体添加到模型空间的块表记录
AcDbObjectId entId;
Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
if (es != Acad::eOk)
{
pBlkTblRcd->close();
delete pEnt; // 添加失败时,要delete
pEnt = NULL;
return AcDbObjectId::kNull;
}
// 关闭模型空间块表记录和实体
pBlkTblRcd->close();
pEnt->close();
return entId;
}
(6)完成sampler函数的代码,他在拖动过程中收集用户信息并更新到成员变量:
//此函数将被drag函数调用以获得用户输入
AcEdJig::DragStatus CDrawSquareJig::sampler()
{
setUserInputControls((UserInputControls)
(AcEdJig::kAccept3dCoordinates
| AcEdJig::kNoNegativeResponseAccepted
| AcEdJig::kNullResponseAccepted));
//一定要判断一下点是否发生了变化,否则update函数不停地被调用,实体反而不能被绘制出来
static AcGePoint3d pointTemp;
DragStatus stat = acquirePoint(m_curPoint);
if (pointTemp != m_curPoint)
{
pointTemp = m_curPoint;
}
else if (stat == AcEdJig::kNormal)
{
return AcEdJig::kNoChange;
}
return stat;
}
关于setUserInputControls函数:
语法:
void setUserInputControls(
AcEdJig::UserInputControls
);
描述:
设置用户输入控制属性。
控制属性:
AcEdJig::kAccept3dCoordinates | 设置“接受Z坐标”模式。默认情况下,输入被限制为2d输入。 |
AcEdJig::kNoNegativeResponseAccepted | 设置“不接受负值”模式。默认值接受负值。这适用于获取函数()和获取角() |
AcEdJig::kNullResponseAccepted | 设置用户输入请求包的“接受空输入”位。默认情况下btit是已知的,不接收null输入 |
(7)添加update函数实现代码
Adesk::Boolean CDrawSquareJig::update()
{
//实现你的更新操作,在这里更新的是m_pPoly
double dist = ToPoint2d(m_centerPoint).distanceTo(ToPoint2d(m_curPoint));
for (int i = 0; i < 4; i++)
{
double angle = i * PI() * 0.5 + PI() *0.25;
AcGePoint2d pt = PolarPoint(ToPoint2d(m_centerPoint), angle, dist);
m_pPoly->setPointAt(i, pt);
}
return Adesk::kTrue;
}
①关于SetPointAt函数:
语法:
Acad::ErrorStatus setPointAt(
Adesk::UInt16 idx,
const AcGePoint3d&
);
描述:
这个函数把idx的值设置为pt.idx必须是0、1、2或3。pt必须在WCS坐标中。
②PI()函数的实现:获得PI的值
double CDrawSquareJig::PI()
{
return atan(1.0) * 4;
}
③PolarPoint函数的实现:根据极坐标的方式推算一个点的坐标
AcGePoint2d CDrawSquareJig::PolarPoint(const AcGePoint2d &basePoint, double angle, double length)
{
double x = basePoint.x + length * cos(angle);
double y = basePoint.y + length * sin(angle);
return AcGePoint2d(x, y);
}
(8)添加entity函数的实现代码:
//指定了Jig所操作的对象
AcDbEntity* CDrawSquareJig::entity() const
{
return m_pPoly;
}
(9)注册一个命令DrawSequareJig,
static void AAAMyGroupSequareJig() {
//提示用户输入中心点
AcGePoint3d centerPoint;
if (CDrawSquareJig::GetPoint(TEXT("\n指定正方形的中心点:"), centerPoint))
{
//进入拖动状态
CDrawSquareJig jig;
AcDbObjectId polyId;
if (jig.doIt(centerPoint, polyId))
{
//成功创建之后,可以进行其他的修改
CDrawSquareJig::SetColor(polyId, 1);
}
else
{
//用户取消,删除已经创建的实体
CDrawSquareJig::Erase(polyId);
}
}
}
其中,
①Erase函数实现:
//删除已经被创建出来的实体
static void Erase(AcDbObjectId entId);
void CDrawSquareJig::Erase(AcDbObjectId entId)
{
AcDbEntity *pEnt = NULL;
if (acdbOpenObject(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
{
pEnt->erase();
pEnt->close();
}
}
②GetPoint函数的实现:
static bool GetPoint(const TCHAR* prompt, AcGePoint3d &point);
bool CDrawSquareJig::GetPoint(const TCHAR* prompt, AcGePoint3d &point)
{
return (GetPointReturnCode(prompt, point) == RTNORM);
}
③GetPointReturnCode函数的实现:
static int GetPointReturnCode(const TCHAR* prompt, AcGePoint3d &point);
int CDrawSquareJig::GetPointReturnCode(const TCHAR* prompt, AcGePoint3d &point)
{
int nReturn = acedGetPoint(NULL, prompt, asDblArray(point));
if (nReturn == RTNORM)
{
point = CDrawSquareJig::UcsToWcsPoint(point);
}
return nReturn;
}
④UcsToWcsPoint函数的实现:
static AcGePoint3d UcsToWcsPoint(const AcGePoint3d &point);
AcGePoint3d CDrawSquareJig::UcsToWcsPoint(const AcGePoint3d &point)
{
// 转换成世界坐标
AcGePoint3d pt;
struct resbuf rbFrom, rbTo;
rbFrom.restype = RTSHORT;
rbFrom.resval.rint = 1; // from UCS
rbTo.restype = RTSHORT;
rbTo.resval.rint = 0; // to WCS
acedTrans(asDblArray(point), &rbFrom, &rbTo, Adesk::kFalse, asDblArray(pt));
return pt;
}
⑤SetColor函数的实现:
static void CDrawSquareJig::SetColor(AcDbObjectId entId, int colorIndex);
void CDrawSquareJig::SetColor(AcDbObjectId entId, int colorIndex)
{
// 检测参数的有效性
assert(colorIndex >= 0 && colorIndex <= 256);
AcDbEntity *pEnt = NULL;
if (acdbOpenObject(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
{
pEnt->setColorIndex(colorIndex);
pEnt->close();
}
}
整个项目的完整代码:
https://pan.baidu.com/s/1k8Jr46uBm1AHaesRRpqGyw
效果:
执行命令SequareJig,在CAD中选取一点为正方形的中心点,拖动鼠标,可得出下图所示图形:
项目流程图:
参考资料:
张帆《AutoCAD ObjectARX(VC)开发基础与实例教程》
上一篇: 基于javaweb调用百度接口实现人脸识别登陆功能
下一篇: python用百度云接口实现车牌号识别