您的位置:首页 > 移动开发 > Objective-C

ObjectARX完美实现一次拖动多个实体(下)

2011-06-26 18:03 671 查看
这次我们来实现一次拖动多个数据库中已存在的实体,就象AuoCAD里的Move、Rotate、Mirror等命令一样。其中的临时实体类具有一定的通用性,只要给它传入不同的变换矩阵就能实现相应的功能。而Jig类的例子则是一个简单的移动示例,大约相当于Move命令的简化版。

临时实体类:

//辅助实体类
//适用于拖动数据库中已经存在的实体,通常是一个选择集选择的实体集
class CDatabaseJigEntity : public AcDbEntity
{
public:
CDatabaseJigEntity(const AcDbObjectIdArray & ids) : m_Ids(ids){}
~CDatabaseJigEntity(){}
virtual Adesk::Boolean worldDraw (AcGiWorldDraw *mode);
void setXform(const AcGeMatrix3d & xform){ m_Xform = xform; }
BOOL transform();
BOOL transformedCopy();
private:
AcDbObjectIdArray	m_Ids;	//保存所有拖动对象的ID
AcGeMatrix3d		m_Xform;//变换矩阵
};
Adesk::Boolean CDatabaseJigEntity::worldDraw(AcGiWorldDraw *mode)
{
//这个地方是关键!
mode->geometry().pushModelTransform(m_Xform);
AcDbEntity* pEnt;
for (int i = 0; i < m_Ids.length(); i++)
{
//绘制实体无需写打开
if (Acad::eOk == acdbOpenObject(pEnt, m_Ids[i],AcDb::kForRead))
{
mode->geometry().draw(pEnt);
pEnt->close();
}
}
//这句不能少,恢复现场
mode->geometry().popModelTransform();
return (AcDbEntity::worldDraw (mode)) ;
}
//用于拖动结束后,将实体变换到新位置
BOOL CDatabaseJigEntity::transform()
{
AcTransaction * pTrans = acTransactionManagerPtr() ->startTransaction();
if (NULL == pTrans)
return FALSE;
AcDbEntity *pEnt;
AcDbObject *pObj;
for (int i= 0; i < m_Ids.length(); i++)
{
if (Acad::eOk != pTrans ->getObject(pObj, m_Ids[i], AcDb::kForWrite))
{
acTransactionManagerPtr() ->abortTransaction();
return FALSE;
}
pEnt = AcDbEntity::cast(pObj);
pEnt ->transformBy(m_Xform);
}
acTransactionManagerPtr() ->endTransaction();
return TRUE;
}
//用于拖动结束后,将实体复制到新位置
BOOL CDatabaseJigEntity::transformedCopy()
{
AcTransaction * pTrans = acTransactionManagerPtr() ->startTransaction();
if (NULL == pTrans)
return FALSE;
AcDbEntity *pEnt;
AcDbEntity *pNewEnt;
AcDbObject *pObj;
AcDbBlockTableRecord *pBlkRec;
AcDbObjectId blkRecId;
for (int i= 0; i < m_Ids.length(); i++)
{
if (Acad::eOk != pTrans ->getObject(pObj, m_Ids[i], AcDb::kForRead))
{
acTransactionManagerPtr() ->abortTransaction();
return FALSE;
}
pEnt = AcDbEntity::cast(pObj);
if (0 == i)
{
blkRecId = pEnt ->blockId();
if (Acad::eOk != pTrans ->getObject(pObj, blkRecId, AcDb::kForWrite))
{
acTransactionManagerPtr() ->abortTransaction();
return FALSE;
}
pBlkRec = AcDbBlockTableRecord::cast(pObj);
}
pEnt ->getTransformedCopy(m_Xform, pNewEnt);
pBlkRec ->appendAcDbEntity(pNewEnt);
acTransactionManagerPtr() ->addNewlyCreatedDBRObject(pNewEnt);
}
acTransactionManagerPtr() ->endTransaction();
return TRUE;
}


用于移动的Jig类:

//移动实体的拖动类
class CMoveJig : public AcEdJig
{
public:
CMoveJig(const AcGePoint3d & fromPoint) : m_pEnt(NULL), m_FromPoint(fromPoint), m_ToPoint(fromPoint){}
~CMoveJig();
void	doIt(const AcDbObjectIdArray & ids, bool bCopy = false);
virtual DragStatus sampler();
virtual Adesk::Boolean update();
virtual AcDbEntity* entity() const;
private:
CDatabaseJigEntity	*m_pEnt;
AcGePoint3d			m_FromPoint;
AcGePoint3d			m_ToPoint;
AcGeMatrix3d		m_Xform;
};
CMoveJig::~CMoveJig()
{
if ( NULL != m_pEnt)
{
delete m_pEnt;
m_pEnt = NULL;
}
}
AcEdJig::DragStatus CMoveJig::sampler()
{
DragStatus stat;
setUserInputControls((UserInputControls)
(AcEdJig::kAccept3dCoordinates
| AcEdJig::kNoNegativeResponseAccepted
| AcEdJig::kNoZeroResponseAccepted
| AcEdJig::kNullResponseAccepted	));
static AcGePoint3d pointTemp;
stat = acquirePoint(m_ToPoint, m_FromPoint);
if (pointTemp != m_ToPoint)
pointTemp = m_ToPoint;
else if (stat == AcEdJig::kNormal)
stat = AcEdJig::kNoChange;
return stat;
}
Adesk::Boolean CMoveJig::update()
{
m_Xform.setToTranslation(m_ToPoint - m_FromPoint);
m_pEnt ->setXform(m_Xform);
return Adesk::kTrue;
}
AcDbEntity * CMoveJig::entity() const
{
return m_pEnt;
}
void CMoveJig::doIt(const AcDbObjectIdArray &ids, bool bCopy /*= false*/)
{
if ( 0 == ids.length() )
{
return;
}
if (NULL != m_pEnt)
{
delete m_pEnt;
m_pEnt = NULL;
}

m_pEnt = new CDatabaseJigEntity(ids);
setDispPrompt(_T("/n移动到: "));
if ( AcEdJig::kNormal == drag() )
{
if (bCopy)
{
m_pEnt ->transformedCopy();
}
else
{
m_pEnt ->transform();
}
}
delete m_pEnt;
m_pEnt = NULL;
}


测试命令:

static void ZDXMyJig_jigmove(void)
{
ads_name ename;
ads_point pt;
ads_name ss;
int rt;

if (rt = acedSSGet(NULL, NULL, NULL, NULL, ss) == RTCAN)
return;
long len;
acedSSLength(ss, &len);
if (0 == len) return;

AcDbObjectId id;
//acdbGetObjectId(id,ename);
AcDbObjectIdArray ids;
for (int i = 0; i < len; i++)
{
acedSSName(ss, i , ename);
acdbGetObjectId(id, ename);
ids.append(id);
}
acedSSFree(ss);
acedGetPoint(NULL, L"/n起点:", pt);

CMoveJig * pJig = new CMoveJig(asPnt3d(pt));
pJig ->doIt(ids);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: