嵌套事务示例 
下面的示例包括三个嵌套事务。事件的顺序如下。 创建嵌套事务
 以下是此示例的代码: 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;
}
 
父主题: | 
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1   苏公网安备32011402011833)
GMT+8, 2025-11-4 19:18
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.