(18)ObjectARX2015 + vs2012插入块参照

1. 说明

        本例允许用户输入一个块参照的名称,指定块参照的插入点等参数,然后将块参照插
入到模型空间。

2. 思路

        AutoCAD 有块定义和块参照两个概念。这两个概念的关系:
        块定义不是一个实体,而是一种对实体的描述,通过定义块获得;
        块参照则是一种实体,图形窗口中显示的“块”都是块参照,通过插入块获得
        在 ObjectARX 编程中,块定义通过块表记录来保存,而块参照由 AcDbBlockReference 类来表示。既然块参照是一种实体,那么创建块参照的过程与创建一条直线似乎不应该有什么区别,事实的确如此!
//AcDbBlockReference 类的构造函数定义为:
//块参照由 AcDbBlockReference 类来表示:
AcDbBlockReference(        
const AcGePoint3d& position,  //position 是块参照的插入点
AcDbObjectId blockTableRec);  //blockTableRec 是块参照所参照的块表记录(块定义)的 ID
3. 步骤
(1) 在CCreateEnt中添加函数AddBlk()
    //插入块参照
    static void InsertBlockReference(); //添加块参照
//插入块参照
void CCreateEnt::InsertBlockReference()
{ 
    // 获得用户输入的块定义名称
    TCHAR blkName[40];
    if (acedGetString(Adesk::kFalse, _T("\n输入图块的名称:"), blkName) != RTNORM) 
    {
        return;
    }

    // 获得当前数据库的块表
    AcDbBlockTable *pBlkTbl;
    acdbHostApplicationServices()->workingDatabase()
        ->getBlockTable(pBlkTbl, AcDb::kForWrite);

    // 查找用户指定的块定义是否存在
    CString strBlkDef;
    strBlkDef.Format(_T("%s"), blkName);
    if (!pBlkTbl->has(strBlkDef))
    {
        acutPrintf(_T("\n当前图形中未包含指定名称的块定义!"));
        pBlkTbl->close();
        return;
    }

    // 获得用户输入的块参照的插入点
    ads_point pt;
    if (acedGetPoint(NULL, _T("\n输入块参照的插入点:"), pt) != RTNORM)
    {
        pBlkTbl->close();
        return;
    }
    AcGePoint3d ptInsert = asPnt3d(pt);
    // 获得用户指定的块表记录
    AcDbObjectId blkDefId;
    pBlkTbl->getAt(strBlkDef, blkDefId);

    // 创建块参照对象
    AcDbBlockReference *pBlkRef = new AcDbBlockReference(ptInsert, blkDefId); 

    // 将块参照添加到模型空间
    AcDbBlockTableRecord *pBlkTblRcd;
    pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite); 
    AcDbObjectId entId;
    pBlkTblRcd->appendAcDbEntity(entId, pBlkRef);

    // 关闭数据库的对象
    pBlkRef->close();
    pBlkTblRcd->close();
    pBlkTbl->close();
}
        AcDbBlockTable::has 函数:为了增加函数的容错能力,增加了判断当前图形的块表中是否包含与指定名称匹配的块表记录的语句。
        acedGetPoint 函数能够暂停程序,等待用户输入一个点,然后获得该点的坐标。
        acedGetPoint 函数定义为:
//acedGetPoint 函数定义为:
//acedGetPoint 函数能够暂停程序,等待用户输入一个点,然后获得该点的坐标。
int acedGetPoint( 
	const ads_point pt,  //pt在当前UCS中指定了一个相对基点,如果指定了该参数,当用户移动鼠标选择要输入
						 //的点时,系统会在光标到基点之间创建一根临时直线,如果不需要基点,可以直接输入NULL;
	const char * prompt, //prompt将会显示在命令行中,给用户提供指导信息,如果不需要该参数,输入NULL即可;
	ads_point result); 	 //result参数返回用户输入的点。

//关于acedGetPoint函数返回值的问题,关于获得用户输入信息的相关内容。
//ads_point 是原来的 ADS 编程中定义的一种数据类型,其定义为:
	typedef ads_real ads_point[3]; 
//ads_real 则被定义为:
	typedef double ads_real;
       ads_point 实际上是一个三维浮点数组,它至今仍在与 ADS 相关的编程中使用。
        从 ads_point 转换到 AcGePoint3d 类型的点,即可以通过数组元素直接赋值,也可以通过
asPnt3d 函数直接转化:
         通过数组元素交换:
                ptInsert[X] = pt[X];
                ptInsert[Y] = pt[Y];
                ptInsert[Z] = pt[Z];
         使用 asPnt3d 函数(需要包含 geassign.h 头文件):
                AcGePoint3d ptInsert = asPnt3d(pt);
                之所以可以使用 X、 Y Z 直接作为数组的下标,是由于这三个字母在 ObjectARX 有特 殊的定义:
                enum { X = 0, Y = 1, Z = 2 };

(2) 在acrxEntryPoint.cpp中

ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyInsertBlockReference, MyInsertBlockReference, ACRX_CMD_MODAL, NULL) //创建块参照
    //当前项目中注册一个命令 InsertBlockReference
    static void MidasMyGroupMyInsertBlockReference()
    {
        //添加长方体
        CCreateEnt::InsertBlockReference();
    }

效果展示

1. 自己创建一个块, 名称为: 测试块

2. 输入命令MyInsertBlockReference

3. 输入要插入块的名称: 测试块

 4. 在需要的位置点击插入块

拓展: 为增强代码的可重用性, 将代码拆分:

    //添加块参照(Id,插入点,比例,旋转角度)
    static AcDbObjectId InsertBlockDef(AcDbObjectId blockRefId, const AcGePoint3d &InsertPoint, const AcGePoint3d, double scale, double roation); //添加块参照(Id,插入点,比例,旋转角度)
    //修改块参照插入比例
    static void SetScaleFactor(AcDbBlockReference *pBlockRef, double scale); //修改块参照插入比例
    //获得指定名称的块定义
    static AcDbObjectId GetBlockDefId(const TCHAR* blockDefName); //获得指定名称的块定义
    //添加块参照
    static void InsertBlockRef(); //添加块参照
//添加块参照(Id,插入点,比例,旋转角度)
AcDbObjectId CCreateEnt::InsertBlockDef(AcDbObjectId blockRefId, const AcGePoint3d &InsertPoint, const AcGePoint3d, double scale, double roation)
{
    //设置图块的插入点,旋转角度,比例
    AcDbBlockReference *pBlockRef = new AcDbBlockReference(InsertPoint, blockRefId);
    pBlockRef->setRotation(roation);
    SetScaleFactor(pBlockRef, scale);

    //把新建的图块参照实体加入到新建的块表记录中,并取得插入实体的ID
    //用于返回值
    return CCreateEnt::PostToModelSpace(pBlockRef);
}


//修改块参照插入比例
void CCreateEnt::SetScaleFactor(AcDbBlockReference *pBlockRef, double scale)
{
    assert(pBlockRef);
    AcGeScale3d geScale(scale, scale, scale);
    pBlockRef->setScaleFactors(geScale);
}


//获得指定名称的块定义
AcDbObjectId CCreateEnt::GetBlockDefId(const TCHAR* blockDefName)
{
    //获得当前数据库的块表
    AcDbBlockTable* pBlockTable = NULL;
    Acad::ErrorStatus es = acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);
    //获得用户指定块表记录
    AcDbObjectId blockDefId;
    es = pBlockTable->getAt(blockDefName, blockDefId);
    //关闭数据库对象
    pBlockTable->close();

    if (es == Acad::eOk)
    {
        return blockDefId;
    }else
    {
        return AcDbObjectId::kNull;
    }
}


//添加块参照
void CCreateEnt::InsertBlockRef()
{
    //获取用户输入的块定义名称
    TCHAR blockName[40];
    if (acedGetString(Adesk::kFalse, _T("\n输入图块的名称:"), blockName) != RTNORM) 
    {
        return;
    }

    //查找用户输入的块定义是否存在
    AcDbObjectId blockDefId = CCreateEnt::GetBlockDefId(blockName);
    if (blockDefId.isNull())
    {
        acutPrintf(_T("\n当前图形中未包含指定名称的块定义!"));
        return;
    }

    //获得用户输入的块参照的插入点
    ads_point pt;
    if (acedGetPoint(NULL, _T("\n输入块参照的插入点: "), pt) != RTNORM)
    {
        return;
    }
    AcGePoint3d ptInsert = asPnt3d(pt);

    //创建块对象对象
    AcDbBlockReference *pblockRef = new AcDbBlockReference(ptInsert, blockDefId);

    //将比例放大一倍
    SetScaleFactor(pblockRef, 2);
    
    //将块参照添加到模型空间
    CCreateEnt::PostToModelSpace(pblockRef);
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值