下面的示例包括三个嵌套事务。事件顺序如下。 创建嵌套事务
下面是此示例的代码: 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-1-8 19:41
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.