development of

Tieghaに関する備忘録とおまけ

【AutoCAD Mechanical】パーツ参照を作成する その2

オブジェクトに関連付いたパーツ参照を作成する

前回の記事ではただパーツ参照を作成しただけでした。
tknmt.hatenablog.com

今回はオブジェクトに関連付けされ、オブジェクトを移動させると追従するパーツ参照を作成してみます。

サンプルコード

// オブジェクトを選択
AmiPickObj PickObj;
if (amiPick(
    _T("\nパーツ参照追加するオブジェクトを選択"),
    AmiKeyType::geomKey,
    NULL,
    PickObj) != Acm::eOk) return;

AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcDbTransactionManager *pTransMgr = pDb->transactionManager();

try
{
    AcTransaction *pTrans = pTransMgr->startTransaction();

    AcDbFullSubentPath subentPath;
    AcGePoint3d pickPoint;
    AcGeVector3d pickVector;
    AcGeMatrix3d viewTrans;
    Adesk::Boolean isGhost;

    // 選択したときの情報を取得
    if (amiGetPickInfo(
        &PickObj,
        subentPath,
        pickPoint,
        pickVector,
        viewTrans,
        isGhost) != Acm::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // パーツ参照を作成
    AcmPartRef *pPartRef = new AcmPartRef();
    pPartRef->setSymbolDefaults(pDb);
    pPartRef->setOrigin(pickPoint);

    // 現在の空間を取得
    AcDbBlockTableRecord *pCurSpace;
    pTrans->getObject((AcDbObject*&)pCurSpace, pDb->currentSpaceId(), AcDb::kForWrite);

    // パーツ参照を現在の空間に追加
    AcDbObjectId partRefId;
    if (pCurSpace->appendAcDbEntity(partRefId, pPartRef) != Acad::eOk)
    {
        delete pPartRef;
        pTransMgr->abortTransaction();
        return;
    }
    pTransMgr->addNewlyCreatedDBRObject(pPartRef);

    // ジオメトリキーを取得
    AmiGeomKey *pObjKey;
    if (amiGetGeomKey(
        Ami::geomKey, 
        Adesk::kTrue, 
        pObjKey, 
        &PickObj) != Acm::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // ジオメトリ参照をアタッチする
    if (pPartRef->attachGeomRef(pObjKey, pickPoint) != Acm::eOk)
    {
        pObjKey->release();
        pTransMgr->abortTransaction();
        return;
    }

    // 現在の標準規格のObjectIdを取得
    AcDbObjectId stdId;
    if (acmStdMgr->getCurrent(stdId) != Acm::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // 現在の標準規格を取得
    AcmStandard *pStandard;
    if (pTrans->getObject((AcDbObject*&)pStandard, stdId, AcDb::kForRead) != Acad::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // BOMの標準規格のObjectIdを取得
    AcDbObjectId bomStdId;
    if (pStandard->getCurrentSymbolStd(L"AcmBOMStd", bomStdId) != Acad::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // BOMの標準規格を取得
    AcmBOMStd *pBOMStd;
    if (pTrans->getObject((AcDbObject*&)pBOMStd, bomStdId, AcDb::kForRead) != Acad::eOk)
    {
        pTransMgr->abortTransaction();
        return;
    }

    // パーツ参照のデータ
    CMapStringToString valueMap;
    int numOfItems = 1;

    // 標準規格の列数だけループ
    for (int i = 0; i < pBOMStd->columnLength(); i++)
    {
        // 列を取得
        const AcmCColumnDef *pColumn = ((const AcmBOMStd*)pBOMStd)->column(i);
        switch (pColumn->type())
        {
        case Acm::kQuantity:
            // 数量を設定
            valueMap.SetAt(pColumn->name(), std::to_wstring(numOfItems).c_str());
            break;
        default:
            // その他の値を設定
            valueMap.SetAt(pColumn->name(), _T(""));
            break;
        }
    }

    // 部品表にパーツ参照のデータをセット
    acmBomMgr->setPartData(partRefId, numOfItems, valueMap);

    pTransMgr->endTransaction();
}
catch (...)
{
    pTransMgr->abortTransaction();
}

※サンプルコードについての補足

パーツ参照を関連付けるオブジェクトの選択には、ObjectARX 標準の acedEntSel 関数や acedSSGet 関数ではなく、amiPick 関数を使用しています。

amiPick 関数は選択したオブジェクト情報だけでなく、選択を行った入力座標などがまとめられた AmiPickObj オブジェクトが出力されます。

選択したときの情報を取得するには amiGetPickInfo 関数を使用します。サンプルコードでは amiGetPickInfo 関数で取得した入力座標を、パーツ参照の原点に設定しています。

パーツ参照を関連付けさせるには AcmPartRef クラスの attachGeomRef メソッドを使用します。 引数には AmiGeomKey オブジェクトとパーツ参照の原点座標を渡していきます。

AmiGeomKey オブジェクトは amiGetGeomKey 関数を使用して、AmiPickObj オブジェクトから取得しています。

実行結果

コマンドを実行した結果、選択したブロックに追従するパーツ参照を作成できました。

f:id:tknmt:20190313100355g:plain