CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

嵌套事务示例

2022-12-31 18:35| 发布者: admin| 查看: 345| 评论: 0|来自: AutoCAD

下面的示例包括三个嵌套事务。事件顺序如下。

创建嵌套事务

  1. 创建一个多边形并将其发布到数据库。
  2. 开始事务 1:
    • 选择多边形并获取指向它的指针。打开它进行阅读。
    • 使用多边形创建拉伸实体。
    • 在扩展多边形的中间创建一个圆柱体。
  3. 开始事务 2:从挤压中减去圆柱体(在固体中间创建一个孔)。
  4. 开始事务 3:
    • 沿X/Z平面将形状切成两半,然后沿X轴移动,以便查看这两个部分。
    • 中止交易?回答是的
  5. 开始事务 3(再次):沿Y/Z平面将形状切成两半,然后沿Y 移动。
  6. 结束事务 3.
  7. 结束事务 2。
    注意:如果此时中止,事务 2 和 3 都将被取消。如果中止包含事务,则所有嵌套事务都将中止,即使它们已成功结束。
  8. 结束事务 1。

下面是此示例的代码:

void
transactCommand()
{
    Adesk::Boolean interrupted;
    Acad::ErrorStatus es = Acad::eOk;
    AcDbObjectId savedCylinderId,savedExtrusionId;
    // Create a poly and post it to the database.
    //
    acutPrintf(_T("\nCreating a poly...Please supply the")
        _T(" required input."));
    if ((es = createAndPostPoly()) != Acad::eOk)
        return;

    // Start a transaction
    //
    AcTransaction *pTrans
        = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf(_T("\n\n######  Started transaction one.  ######\n"));

    // Select the poly and extrude it.
    //
    AcDbObject   *pObj = NULL;
    AsdkPoly     *pPoly = NULL;
    AcDb3dSolid  *pSolid = NULL;
    AcDbObjectId  objId;

    ads_name      ename;
    ads_point     pickpt;

    for (;;) {

        switch (acedEntSel(_T("\nSelect a polygon: "), ename, pickpt))
        {

        case RTNORM:
            acdbGetObjectId(objId, ename);
            if ((es = pTrans->getObject(pObj, objId,
                AcDb::kForRead)) != Acad::eOk)
            {
                acutPrintf(_T("\nFailed to obtain an object through transaction."));
                actrTransactionManager->abortTransaction();
                return;
            }
            assert(pObj != NULL);

            pPoly = AsdkPoly::cast(pObj);
            if (pPoly == NULL) {
                acutPrintf(_T("\nNot a polygon. Try again"));
                continue;
            }
            break;

        case RTNONE:
        case RTCAN:
            actrTransactionManager->abortTransaction();
            return;
        default:
            continue;
        }
        break;
    }

    // Now that we have a poly, convert it to a region
    // and extrude it.
    //
    acutPrintf(_T("\nWe will be extruding the poly."));
    AcGePoint2d c2d = pPoly->center();
    ads_point pt;
    pt[0] = c2d[0]; pt[1] = c2d[1]; pt[2] = pPoly->elevation();
    acdbEcs2Ucs(pt,pt,asDblArray(pPoly->normal()),Adesk::kFalse);
    double height;
    if (acedGetDist(pt, _T("\nEnter Extrusion height: "),
        &height) != RTNORM)
    {
        actrTransactionManager->abortTransaction();
        return;
    }

    if ((es = extrudePoly(pPoly, height,savedExtrusionId)) != Acad::eOk) {
        actrTransactionManager->abortTransaction();
        return;
    }

    // Create a cylinder at the center of the polygon of
    // the same height as the extruded poly.
    //
    double radius = (pPoly->startPoint() - pPoly->center()).length() * 0.5;

    pSolid = new AcDb3dSolid;
    assert(pSolid != NULL);
    pSolid->createFrustum(height, radius, radius, radius);

    AcGeMatrix3d mat(AcGeMatrix3d::translation(pPoly->elevation()*pPoly->normal())*
        AcGeMatrix3d::planeToWorld(pPoly->normal()));
    pSolid->transformBy(mat);

    // Move it up again by half the height along
    // the normal.
    //
    AcGeVector3d x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
    AcGePoint3d  moveBy(pPoly->normal()[0] * height * 0.5, 
                        pPoly->normal()[1] * height * 0.5, 
                        pPoly->normal()[2] * height * 0.5);
    mat.setCoordSystem(moveBy, x, y, z);
    pSolid->transformBy(mat);

    // Move it, so center of cylinder will equal center of poly
    AcGePoint3d pt1;
    pPoly->getCenter (pt1);
    AcGeMatrix3d mat1(AcGeMatrix3d::translation(pt1 - AcGePoint3d ()));
    pSolid->transformBy(mat1);

    addToDb(pSolid, savedCylinderId);
    actrTransactionManager->addNewlyCreatedDBRObject(pSolid);
    pSolid->draw();
    acutPrintf(_T("\nCreated a cylinder at the center of the poly."));

    // Start another transaction. Ask the user to select
    // the extruded solid followed by selecting the
    // cylinder. Make a hole in the extruded solid by
    // subtracting the cylinder from it.
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf(_T("\n\n######  Started transaction two.  ######\n"));

    AcDb3dSolid *pExtrusion, *pCylinder;
    if ((es = getASolid(_T("\nSelect the extrusion: "), pTrans, 
        AcDb::kForWrite, savedExtrusionId, pExtrusion))
        != Acad::eOk)
    {
        actrTransactionManager->abortTransaction();
        actrTransactionManager->abortTransaction();
        return;
    }
    assert(pExtrusion != NULL);

    if ((es = getASolid(_T("\nSelect the cylinder: "), pTrans, 
        AcDb::kForWrite, savedCylinderId, pCylinder))
        != Acad::eOk)
    {
        actrTransactionManager->abortTransaction();
        actrTransactionManager->abortTransaction();
        return;
    }
    assert(pCylinder != NULL);

    pExtrusion->booleanOper(AcDb::kBoolSubtract, pCylinder);
    pExtrusion->draw();
    acutPrintf(_T("\nSubtracted the cylinder from the extrusion."));

    // At this point, cylinder is a NULL solid. We might
    // as well erase it.
    //
    assert(pCylinder->isNull());
    pCylinder->erase();

    // Start another transaction and slice the resulting
    // solid into two halves. 
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf(_T("\n\n#####  Started transaction three.  ######\n"));

    AcGeVector3d vec, normal;
    AcGePoint3d sp,center;
    pPoly->getStartPoint(sp);
    pPoly->getCenter(center);
    vec = sp - center;
    normal = pPoly->normal().crossProduct(vec);
    normal.normalize();
    AcGePlane sectionPlane(center, normal);

    AcDb3dSolid *pOtherHalf = NULL;
    pExtrusion->getSlice(sectionPlane, Adesk::kTrue,
        pOtherHalf);
    assert(pOtherHalf != NULL);

    // Move the other half three times the vector length
    // along the vector.
    //
    moveBy.set(vec[0] * 3.0, vec[1] * 3.0, vec[2] * 3.0);
    mat.setCoordSystem(moveBy, x, y, z);
    pOtherHalf->transformBy(mat);
    AcDbObjectId otherHalfId;
    addToDb(pOtherHalf, otherHalfId);
    actrTransactionManager->addNewlyCreatedDBRObject(pOtherHalf);
    pOtherHalf->draw();
    pExtrusion->draw();
    acutPrintf(_T("\nSliced the resulting solid into half and moved one piece."));

    // After all this work, let's abort transaction three,
    // so that we are back to the hole in the extrusion.
    //
    Adesk::Boolean yes = Adesk::kTrue;
    if (getYOrN(_T("\nLet's abort transaction three, yes?")
        _T(" [Y] : "), Adesk::kTrue, yes,interrupted) == Acad::eOk 
        && yes == Adesk::kTrue)
    {
        acutPrintf(_T("\n\n$$$$$$  Aborting transaction three. $$$$$$\n"));
        actrTransactionManager->abortTransaction();
        acutPrintf(_T("\nBack to the un-sliced solid."));
        pExtrusion->draw();
        TCHAR option[256];
        acedGetKword(_T("\nHit any key to continue."), option);
    } else {
        acutPrintf(_T("\n\n>>>>>>  Ending transaction three.  <<<<<<\n"));
        actrTransactionManager->endTransaction();
    }

    // Start another transaction (three again). This time
    // slice the solid along a plane that is perpendicular
    // to the plane we used last time. That's the slice
    // we really wanted.
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf(_T("\n\n#####  Started transaction three.  ######\n"));

    moveBy.set(normal[0] * 3.0, normal[1] * 3.0,
        normal[2] * 3.0);
    normal = vec;
    normal.normalize();
    sectionPlane.set(center, normal);

    pOtherHalf = NULL;
    pExtrusion->getSlice(sectionPlane, Adesk::kTrue,
        pOtherHalf);
    assert(pOtherHalf != NULL);

    mat.setCoordSystem(moveBy, x, y, z);
    pOtherHalf->transformBy(mat);
    addToDb(pOtherHalf, otherHalfId);
    actrTransactionManager
        ->addNewlyCreatedDBRObject(pOtherHalf);
    pOtherHalf->draw();
    pExtrusion->draw();
    acutPrintf(_T("\nSliced the resulting solid into half along a plane"));
    acutPrintf(_T("\nperpendicular to the old one and moved one piece."));

    // Now, optionally, let's end all the transactions.
    //
    yes = Adesk::kFalse;
    if (getYOrN(_T("\nAbort transaction three? <No> : "),
        Adesk::kFalse, yes,interrupted) == Acad::eOk 
        && yes == Adesk::kTrue)
    {
        acutPrintf(_T("\n\n$$$$$$  Aborting transaction three. $$$$$$\n"));
        actrTransactionManager->abortTransaction();
        acutPrintf(_T("\nBack to the un-sliced solid."));
    } else {
        acutPrintf(_T("\n\n>>>>>>  Ending transaction three.  <<<<<<\n"));
        actrTransactionManager->endTransaction();
    }

    yes = Adesk::kFalse;
    if (getYOrN(_T("\nAbort transaction two? <No> : "),
        Adesk::kFalse, yes,interrupted) == Acad::eOk 
        && yes == Adesk::kTrue)
    {
        acutPrintf(_T("\n\n$$$$$$  Aborting transaction two.  $$$$$$\n"));
        actrTransactionManager->abortTransaction();
        acutPrintf(_T("\nBack to separate extrusion and cylinder."));
    } else {
        acutPrintf(_T("\n\n>>>>>>  Ending transaction two.  <<<<<<\n"));
        actrTransactionManager->endTransaction();
    }

    yes = Adesk::kFalse;
    if (getYOrN(_T("\nAbort transaction one? <No> : "),
        Adesk::kFalse, yes,interrupted) == Acad::eOk 
        && yes == Adesk::kTrue)
    {
        acutPrintf(_T("\n\n$$$$$$  Aborting transaction one.  $$$$$$\n"));
        actrTransactionManager->abortTransaction();
        acutPrintf(_T("\nBack to just the Poly."));
    } else {
        actrTransactionManager->endTransaction();
        acutPrintf(_T("\n\n>>>>>>  Ending transaction one.  <<<<<<\n"));
    }
}


static Acad::ErrorStatus
createAndPostPoly()
{
    int nSides = 0;

    while (nSides < 3) {

        acedInitGet(INP_NNEG, _T(""));
        switch (acedGetInt(_T("\nEnter number of sides: "), &nSides))
        {

        case RTNORM:
            if (nSides < 3)
               acutPrintf(_T("\nNeed at least 3 sides."));
            break;
        default:
            return Acad::eInvalidInput;
        }
    }

    ads_point center, startPt, normal;

    if (acedGetPoint(NULL, _T("\nLocate center of polygon: "),
        center) != RTNORM)
    {
        return Acad::eInvalidInput;
    }

    startPt[0] = center[0];
    startPt[1] = center[1];
    startPt[2] = center[2];
    
    while (asPnt3d(startPt) == asPnt3d(center)) {
        switch (acedGetPoint(center,
            _T("\nLocate start point of polygon: "), startPt)) {
            case RTNORM:
                if (asPnt3d(center) == asPnt3d(startPt))
                    acutPrintf(_T("\nPick a point different from the center."));
                break;
            default:
                return Acad::eInvalidInput;
        }
    }


    // Set the normal to the plane of the polygon to be
    // the same as the z direction of the current ucs,
    // i.e. (0, 0, 1) since we also got the center and
    // start point in the current UCS. (acedGetPoint()
    // returns in the current UCS.)

    normal[X] = 0.0;
    normal[Y] = 0.0;
    normal[Z] = 1.0;

    acdbUcs2Wcs(normal, normal, Adesk::kTrue);
    acdbUcs2Ecs(center, center, normal, Adesk::kFalse);
    acdbUcs2Ecs(startPt, startPt, normal, Adesk::kFalse);
    double elev = center[2];
    AcGePoint2d cen = asPnt2d(center),
                start = asPnt2d(startPt);
    AcGeVector3d norm = asVec3d(normal);

    AsdkPoly *pPoly = new AsdkPoly;

    if (pPoly==NULL)
        return Acad::eOutOfMemory;
    Acad::ErrorStatus es;
    if ((es=pPoly->set(cen, start, nSides, norm, _T("transactPoly"), elev))!=Acad::eOk)
        return es;

    pPoly->setDatabaseDefaults(acdbHostApplicationServices()->workingDatabase());
    postToDb(pPoly);

    return Acad::eOk;
}



// Extrudes the poly to a given height.

static Acad::ErrorStatus
extrudePoly(AsdkPoly* pPoly, double height, AcDbObjectId& savedExtrusionId)
{
    Acad::ErrorStatus es = Acad::eOk;

    // Explode to a set of lines
    //
    AcDbVoidPtrArray lines;
    pPoly->explode(lines);

    // Create a region from the set of lines.
    //
    AcDbVoidPtrArray regions;
    AcDbRegion::createFromCurves(lines, regions);
    assert(regions.length() == 1);
    AcDbRegion *pRegion = AcDbRegion::cast((AcRxObject*)regions[0]);
    assert(pRegion != NULL);

    // Extrude the region to create a solid.
    //
    AcDb3dSolid *pSolid = new AcDb3dSolid;
    assert(pSolid != NULL);
    pSolid->extrude(pRegion, height, 0.0);

    for (int i = 0; i < lines.length(); i++) {
        delete (AcRxObject*)lines[i];
    }
    for (int ii = 0; ii < regions.length(); ii++) {
        delete (AcRxObject*)regions[ii];
    }

    // Now we have a solid. Add it to database, then
    // associate the solid with a transaction. After
    // this, transaction management is in charge of
    // maintaining it.
    //

    pSolid->setPropertiesFrom(pPoly);
    addToDb(pSolid, savedExtrusionId);
    actrTransactionManager->addNewlyCreatedDBRObject(pSolid);
    pSolid->draw();

    return Acad::eOk;
}


static Acad::ErrorStatus
getASolid(TCHAR*          prompt, 
          AcTransaction* pTransaction, 
          AcDb::OpenMode mode,
          AcDbObjectId   checkWithThisId,
          AcDb3dSolid*&  pSolid)
{
    AcDbObject   *pObj = NULL;
    AcDbObjectId  objId;

    ads_name      ename;
    ads_point     pickpt;

    for (;;) {

        switch (acedEntSel(prompt, ename, pickpt)) {

        case RTNORM:

            acdbGetObjectId(objId, ename);
            if (objId != checkWithThisId) {
                acutPrintf(_T("\n Select the proper solid."));
                continue;
            }

            pTransaction->getObject(pObj, objId, mode);
            assert(pObj != NULL);

            pSolid = AcDb3dSolid::cast(pObj);
            if (pSolid == NULL) {
                acutPrintf(_T("\nNot a solid. Try again"));
                continue;
            }
            break;

        case RTNONE:
        case RTCAN:
            return Acad::eInvalidInput;
        default:
            continue;
        }
        break;
    }

    return Acad::eOk;
}

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 14:35

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部