天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 63|回复: 0

ObjectARX2015 + vs2012利用 Transform 实现复制、移动等操作

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
说明

        对实体执行一些移动、旋转、镜像等操作,这种情况下可以直接使用 acedCommand 函数调用相关的 AutoCAD 内部命令,也可以使用 AcDbEntity 类的 transformBy 函数,对实体进行相应的变换操作。

        实际上使用第一种方法在某些特定的情况下有一个致命的问题。由于 AutoCAD 内部命令和 ObjectARX 注册的命令在不同的线程中执行,因此有可能导致使用 acedCommand 函数的命令执行过程发生错乱。

        本篇的程序介绍使用 transformBy 函数对实体进行几何变换,其中的一些方法使用ObjectARX 中提供的一些基于 COM(组件对象模型)的全局函数来实现。
2. 思路
(1)  使用 transformBy函数进行几何变换( transformBy 函数 )
        transformBy 是 AcDbEntity 类的一个成员函数,该函数使用一个 AcGeMatrix3d 参数对实
体进行相应的几何变换,所有 AcDbEntity 的派生类都实现了这个虚函数,因此所有的实体都可以使用这种方法进行几何变换。
        函数原型为:
virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);
        AcGeMatrix3d是一个几何类,用于表示一个四维矩阵,基本形式如图:

                        AcGeMatrix3d 提供了一些很有用的成员函数:
                                 setToTranslation:生成一个移动对象的矩阵。
                                 setToRotation:生成旋转矩阵。
                                 setToScaling:生成比例缩放矩阵。
                                 setToMirroring:生成镜像矩阵。
(2)复制实体( clone 函数)
        AcDbObject 类拥有一个 clone 函数,能否生成一个调用者的克隆对象,并返回指向克隆对象的指针。由于所有实体对应的类都间接继承于 AcDbObject 类( AcDbEntity 类从 AcDbObject 类继承),因此所有实体都可以用这种方法进行克隆。
        (克隆后把它 添加到模型 空间中)
        clone 函数仅仅会生成对象的一个克隆,对于实体对象来说,这样还没有完成复制操作的全部。在创建实体时我们已经了解到, 创建实体仅仅是第一个步骤,还必须把它添加到模型空间中才能被显示出来 ,对于克隆得到的实体同样需要这样做。
(3) 使用 AcAxXXX 全局函数
        在 ObjectARX 中有一系列 AcAx 开头的全局函数,这些函数通过 COM 的方式来让
AutoCAD 完成一些操作,这一篇我们能使用
                        AcAxMove、AcAxRotate 、   AcAxScaleEntity 函数分别完成
                        移动、          旋转、             缩放实体              的操作。
3. 步骤
(1) 对实体进行移动:使用 transformBy 函数
        使用 transformBy 函数移动实体的关键在于构建符合要求的 AcGeMatrix3d 对象,
AcGeMatrix3d 类的 setToTranslation 函数用于完成这个功能,它所接受的参数是一个三维矢
量,因此先根据移动的基点和目的点构建了一个 AcGeVector3d 对象。
//移动实体:使用 transformBy 函数
static Acad::ErrorStatus MoveEnt(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo);
//移动实体:使用 transformBy 函数
Acad::ErrorStatus CCreateEnt::MoveEnt(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo)
{
        // 构建用于实现移动实体的矩阵
        AcGeVector3d vec(ptTo[X] - ptFrom[X], ptTo[Y] - ptFrom[X], ptTo[Z] - ptFrom[Z]);
        AcGeMatrix3d mat;
        mat.setToTranslation(vec);
        AcDbEntity *pEnt = NULL;
        Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite);
        if (es != Acad::eOk)
                return es;
        es = pEnt->transformBy(mat);
        pEnt->close();
        return es;
}

(2) 对实体的移动:使用 AcAxMove 全局函数
//对实体的移动:使用 AcAxMove 全局函数
BOOL AcMove(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo);
//对实体的移动:使用 AcAxMove 全局函数
BOOL CGeometryOper::AcMove(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo)
{
        // 将AcGePoint3d类型的点坐标进行类型转换
        VARIANT *pvaFrom = Point3dToVARIANT(ptFrom);
        VARIANT *pvaTo = Point3dToVARIANT(ptTo);
        BOOL bRet = SUCCEEDED(AcAxMove(entId, *pvaFrom, *pvaTo));
        delete pvaFrom;
        delete pvaTo;
        return bRet;
}
        Point3dToVARIANT 是一个自定义函数,能根据 AcGePoint3d 对象生成一个 VARIANT
类型的对象,并返回指向该对象的指针。
        Point3dToVARIANT 函数的定义为:
//Point3dToVARIANT函数自定义
static VARIANT* Point3dToVARIANT(const AcGePoint3d &point)
{
        COleSafeArray *psa = new COleSafeArray();
        DOUBLE dblValues[] = {point[X], point[Y], point[Z]};
        psa->CreateOneDim(VT_R8, 3, dblValues);
        return (LPVARIANT)(*psa);
}

//static 关键字限制了 Point3dToVARIANT 函数的作用域,在该文件之外不能使用这个函数。
//在 C++编程中,应该给函数尽量小的作用域,全局函数更要尽量避免出现,
//使用 static函数限制函数的作用域是一个好的方法。
        由于 VARIANT 和 COleSafeArray 都无法直接作为函数的返回值,它们的复制操作必须使用专门的函数,而不像 C++中的标准类型直接可以复制拷贝,也就是说,下面的函数返回值总是无效的。

static COleSafeArray Point3dToVARIANT(const AcGePoint3d &point)
{
    COleSafeArray sa;
    DOUBLE dblValues[] = {point[X], point[Y], point[Z]};
    sa.CreateOneDim(VT_R8, 3, dblValues);
    return sa;
}
        由于在 Point3dToVARIANT 函数中使用 new 关键字动态分配了内存,那么调用它的函数必须释放返回值的内存空间,在 AcMove 函数中就分别释放了 pvaFrom 和 pvaTo 所指向变量的空间。

(3)移动实体:对给定 ID 的实体的一个克隆,并且按照 ptFrom 和 ptTo 生成的矢量移动生成的克隆对象
//移动实体:对给定 ID 的实体的一个克隆,并且按照 ptFrom 和 ptTo 生成的矢量移动生成的克隆对象,
BOOL CopyEnt(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo);
//移动实体:对给定 ID 的实体的一个克隆,并且按照 ptFrom 和 ptTo 生成的矢量移动生成的克隆对象,
BOOL CGeometryOper::CopyEnt(AcDbObjectId entId, const AcGePoint3d &ptFrom, const AcGePoint3d &ptTo)
{
        AcDbEntity *pEnt = NULL;
        if (acdbOpenObject(pEnt, entId, AcDb::kForRead) != Acad::eOk)
                return FALSE;
        AcDbEntity *pCopyEnt = AcDbEntity::cast(pEnt->clone());
        AcDbObjectId copyEntId;
        if (pCopyEnt)
                copyEntId = PostToModelSpace(pCopyEnt);

        MoveEnt(copyEntId, ptFrom, ptTo);
        return TRUE;
}
        clone 函数能够生成调用者的一个克隆,该函数是 AcDbObject 类的一个成员函数,其原
型为:
virtual AcRxObject* clone() const;
        由于函数的返回值不是 AcDbEntity 类型的指针,因此必须通过一个很常用的方法进行实体指针的升级:

AcDbEntity *pCopyEnt = AcDbEntity::cast(pEnt->clone());
        Copy 函数中, PostToModelSpace 函数用于将实体添加到模型空间,同样使用 static 关键
字来限制其名称的可见性:
static AcDbObjectId 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;
}

(5)旋转实体

//旋转实体
Acad::ErrorStatus Rotate(AcDbObjectId entId, const AcGePoint2d &ptBase, double angle)
//旋转实体
Acad::ErrorStatus CGeometryOper::Rotate(AcDbObjectId entId, const AcGePoint2d &ptBase, double angle)
{
        // 构建变换矩阵
        AcGeMatrix3d mat;
        mat.setToRotation(angle, AcGeVector3d::kZAxis,
                AcGePoint3d(ptBase[X], ptBase[Y], 0.));
        // 对实体进行变换
        AcDbEntity *pEnt = NULL;
        Acad::ErrorStatus es = acdbOpenObject(pEnt, entId,
                AcDb::kForWrite);
        if (es != Acad::eOk)
                return es;
        es = pEnt->transformBy(mat);
        pEnt->close();
        return es;
}


 

 

 

 

ObjectARX2015 + vs2012利用 Transform 实现复制、移动等操作
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 11:27 , Processed in 0.150548 second(s), 28 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表