ObjectArx 实现类似C# 的DrawJig,支持多实体拖动
首先实现接口,因为AcEdJig 仅仅支持单实体进行更新显示,如果用多实体那么就需要一个AcDbEntity 去包装,本次我们换个方式,直接在类中加入AcDbEntity接口,实现subWorldDraw显示多个图元class DrawJig : public AcDbEntity, public AcEdJig {
public:
virtual DragStatus sampler() = 0;
virtual boolupdate() = 0;
virtual bool subWorldDraw(AcGiWorldDraw* mode) = 0;
protected:
AcDbEntity* entity() const final
{
return (AcDbEntity*)this;
}
};下面用一个简单的例子继承测试下
class TestDrrawJig :public DrawJig {
public:
TestDrrawJig() {}
bool startDrag(AcGePoint3d ptCenter);
DragStatus sampler() override;
bool update() override;
bool subWorldDraw(AcGiWorldDraw* mode)override;
AcGePoint2d Point3dTo2d(AcGePoint3d pnt);
AcDbVoidPtrArray CreateEntitys();
AcArray<AcDbEntity*> GetEntities();
private:
AcGePoint3d m_centerPnt;
AcGePoint3d m_curPnt;
AcDbVoidPtrArray m_aryPtr;
};
inline AcEdJig::DragStatus TestDrrawJig::sampler()
{
setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates
| AcEdJig::kNoNegativeResponseAccepted
| AcEdJig::kNullResponseAccepted));
AcGePoint3d pointTemp;
DragStatus stat = acquirePoint(m_curPnt);
if (pointTemp != m_curPnt)
{
pointTemp = m_curPnt;
}
else if (stat == AcEdJig::kNormal)
{
return AcEdJig::kNoChange;
}
return stat;
}
inline bool TestDrrawJig::update()
{
for (int i = 0; i < m_aryPtr.length(); i++)
{
AcDbEntity* pEnt = (AcDbEntity*)m_aryPtr.at(i);
delete pEnt;
pEnt = NULL;
}
//创建新实体
m_aryPtr = CreateEntitys();
return Adesk::kTrue;
}
inline bool TestDrrawJig::subWorldDraw(AcGiWorldDraw* mode)
{
for (int i = 0; i < m_aryPtr.length(); i++)
{
AcDbEntity* pEnt = (AcDbEntity*)m_aryPtr;
mode->geometry().draw(pEnt);
}
return Adesk::kTrue;
}
inline AcGePoint2d TestDrrawJig::Point3dTo2d(AcGePoint3d pnt)
{
return AcGePoint2d(pnt.x, pnt.y);
}
inline AcDbVoidPtrArray TestDrrawJig::CreateEntitys()
{
AcDbVoidPtrArray aryEnts;
//创建实体
double dist = Point3dTo2d(m_curPnt).distanceTo(Point3dTo2d(m_centerPnt));
AcGeVector2d vec = Point3dTo2d(m_curPnt) - Point3dTo2d(m_centerPnt);
AcGePoint2d pt1, pt2, pt3, pt4;
pt1 = Point3dTo2d(m_curPnt);
pt3 = pt1 - 2 * vec;
vec.rotateBy(PI * 0.5);
pt2 = Point3dTo2d(m_centerPnt) + vec;
pt4 = pt2 - 2 * vec;
AcDbPolyline* poly = new AcDbPolyline;
poly->addVertexAt(0, pt1);
poly->addVertexAt(1, pt2);
poly->addVertexAt(2, pt3);
poly->addVertexAt(3, pt4);
poly->setClosed(Adesk::kTrue);
poly->setColorIndex(1);
aryEnts.append(static_cast<void*>(poly));
AcDbCircle* circle = new AcDbCircle(m_centerPnt, AcGeVector3d::kZAxis, pt1.distanceTo(pt2) * 0.5);
circle->setColorIndex(3);
aryEnts.append(static_cast<void*>(circle));
return aryEnts;
}
inline AcArray<AcDbEntity*> TestDrrawJig::GetEntities()
{
AcArray <AcDbEntity*> ents;
for (int i = 0; i < m_aryPtr.length(); i++) {
ents.append((AcDbEntity*)(m_aryPtr));
}
return ents;
}
inline bool TestDrrawJig::startDrag(AcGePoint3d ptCenter)
{
m_centerPnt = ptCenter;
m_curPnt = ptCenter;
AcString prompt = _T("\n指定角点");
setDispPrompt(prompt);
AcEdJig::DragStatus stat = drag();
if (stat == AcEdJig::kNormal)
{
return true;
}
else
{
return false;
}
}void tsJig()
{
DbTrans tr;
auto btr = tr.CurrentSpace();
auto res = MapleGetPoint();
if (!res.Ok) return;
TestDrrawJig jig;
if (jig.startDrag(res.Value)) {
auto ents = jig.GetEntities();
tr.AddEntities(btr, ents);
}
}这样就可以使用多实体Jig了,与C#的DrawJig 差不多
arx本来就有,类似c#不知道几个意思 本帖最后由 cable2004 于 2025-5-17 19:12 编辑
class CMoveJig : public AcEdJig {
public:
CMoveJig() : mBasePoint(), mCurrentPoint(), mOffset() {}
AcEdJig::DragStatus Start(const AcDbObjectIdArray& objIds, const AcGePoint3d& basePoint) {
mObjIds = objIds;
mBasePoint = basePoint;
mCurrentPoint = basePoint;
mOffset.set(0.0, 0.0, 0.0);
if (!PrepareDisplayEntities()) {
return kCancel;
}
setDispPrompt(_T("\n指定目标点: "));
setSpecialCursorType(AcEdJig::kCrosshair);
DragStatus stat = drag();
if (stat == kNormal) {
MoveOriginalEntities();
}
CleanupDisplayEntities();
return stat;
}
protected:
virtual DragStatus sampler() {
AcGePoint3d newPt;
DragStatus stat = acquirePoint(newPt, mBasePoint);
if (stat == kNormal && !newPt.isEqualTo(mCurrentPoint)) {
mCurrentPoint = newPt;
mOffset = mCurrentPoint - mBasePoint;
return kNormal;
}
return stat;
}
virtual Adesk::Boolean update() {
AcGeMatrix3d xform;
xform.setToTranslation(mOffset); // 创建平移矩阵
for (int i = 0; i < mDisplayEntities.length(); ++i) {
if (mDisplayEntities) {
mDisplayEntities->transformBy(xform);
}
}
acedRedraw(NULL, 1);
return Adesk::kTrue;
}
// 返回第一个实体作为主实体
virtual AcDbEntity* entity() const override {
return mDisplayEntities.isEmpty() ? NULL : mDisplayEntities;
}
// 添加额外方法获取所有实体
const AcArray<AcDbEntity*>& entities() const {
return mDisplayEntities;
}
virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWorldDraw) {
for (int i = 0; i < mDisplayEntities.length(); ++i) {
if (mDisplayEntities) {
mDisplayEntities->worldDraw(pWorldDraw);
if (mDisplayEntities != NULL)
{
pWorldDraw->geometry().draw(mDisplayEntities);
}
}
}
return Adesk::kTrue;
}
private:
AcDbObjectIdArray mObjIds;
AcGePoint3d mBasePoint;
AcGePoint3d mCurrentPoint;
AcGeVector3d mOffset;
AcArray<AcDbEntity*> mDisplayEntities;
bool PrepareDisplayEntities() {
for (int i = 0; i < mObjIds.length(); ++i) {
AcDbEntity* pEnt = NULL;
if (acdbOpenObject(pEnt, mObjIds, AcDb::kForRead) == Acad::eOk) {
AcDbEntity* pClone = static_cast<AcDbEntity*>(pEnt->clone());
if (pClone) {
mDisplayEntities.append(pClone);
}
pEnt->close();
}
}
return mDisplayEntities.length() > 0;
}
void CleanupDisplayEntities() {
for (int i = 0; i < mDisplayEntities.length(); ++i) {
if (mDisplayEntities) {
delete mDisplayEntities;
}
}
mDisplayEntities.removeAll();
}
void MoveOriginalEntities() {
AcGeMatrix3d xform;
xform.setToTranslation(mOffset); // 创建平移矩阵
for (int i = 0; i < mObjIds.length(); ++i) {
AcDbEntity* pEnt = NULL;
if (acdbOpenObject(pEnt, mObjIds, AcDb::kForWrite) == Acad::eOk) {
pEnt->transformBy(xform);
pEnt->close();
}
}
}
};
// 移动选中对象命令入口函数
static void Cmd_MoveSelected() {
ads_name ss;
if (RTNORM != acedSSGet(NULL, NULL, NULL, NULL, ss)) {
acutPrintf(_T("\n未选择对象"));
return;
}
AcDbObjectIdArray objIds;
Adesk::Int32 length = 0;
acedSSLength(ss, &length);
for (long i = 0; i < length; ++i) {
ads_name ent;
acedSSName(ss, i, ent);
AcDbObjectId id;
acdbGetObjectId(id, ent);
objIds.append(id);
}
acedSSFree(ss);
ads_point pt;
if (RTNORM != acedGetPoint(NULL, _T("\n指定基点: "), pt)) {
return;
}
acdbUcs2Wcs(pt, pt, false);
AcGePoint3d basePt = asPnt3d(pt);
CMoveJig jig;
jig.Start(objIds, basePt);
}
模仿一个move移动的功能,为什么不能时时看到移动的过程,最终结果是对的。
页:
[1]