【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 &centerPoint,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 &centerPoint,
	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)开发基础与实例教程》 

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容