01/08/2018
Как сделать вставку точки в разрыв кривой?
Как сделать вставку точки в разрыв кривой?
На форуме мне задали вопрос о том, как можно эмулировать команду _BREAK и вставлять в разрыв точку? Ниже код, показывающий как используя метод getSplitCurves можно добиться результата.
Код - C++: [Выделить]
- //-----------------------------------------------------------------------------
- //----- acrxEntryPoint.cpp
- //-----------------------------------------------------------------------------
- #include "StdAfx.h"
- #include "resource.h"
- //-----------------------------------------------------------------------------
- #define szRDS _RXST("")
- //-----------------------------------------------------------------------------
- //----- ObjectARX EntryPoint
- class CBreakLineApp : public AcRxArxApp {
- public:
- CBreakLineApp() : AcRxArxApp() {}
- virtual AcRx::AppRetCode On_kInitAppMsg(void *pkt) {
- AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg(pkt);
- return (retCode);
- }
- virtual AcRx::AppRetCode On_kUnloadAppMsg(void *pkt) {
- AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg(pkt);
- return (retCode);
- }
- virtual void RegisterServerComponents() { }
- //////////////////////////////////////////////////////////////////////////
- // Adding entity to Database
- //////////////////////////////////////////////////////////////////////////
- static Acad::ErrorStatus postToDwg(AcDbEntity *pEnt, AcDbDatabase *pDb = NULL, ACHAR *requiredSpace = NULL)
- {
- Acad::ErrorStatus es;
- if (pDb == NULL) pDb = acdbCurDwg();
- AcDbBlockTableRecordPointer blockTableRecord;
- if (requiredSpace)
- {
- es = blockTableRecord.open(requiredSpace, pDb, AcDb::kForWrite);
- }
- else
- {
- es = blockTableRecord.open(pDb->currentSpaceId(), AcDb::kForWrite);
- }
- if (es != Acad::eOk)
- return (es);
- es = blockTableRecord->appendAcDbEntity(pEnt);
- return (es);
- }
- static void RivilisBreakLine()
- {
- ads_name en;
- AcGePoint3d p;
- Acad::ErrorStatus es = Acad::eOk;
- //////////////////////////////////////////////////////////////////////////
- // Расчет длины зазора
- //////////////////////////////////////////////////////////////////////////
- resbuf rb;
- acedGetVar(_ACRX_T("PDSIZE"), &rb);
- double radius = rb.resval.rreal * 0.5;
- // Если PDSIZE = 0, то это 5 процентов от высоты вида
- if (radius < 1e-12 && radius > -1e-12)
- radius = -5.0;
- // Если PDSIZE < 0, то это процент от высоты вида
- if (radius <= 1e-12)
- {
- acedGetVar(_ACRX_T("VIEWSIZE"), &rb);
- radius = -radius * rb.resval.rreal / 100.0;
- }
- //////////////////////////////////////////////////////////////////////////
- if (acedEntSel(L"\nВыберите кривую в точке разрыва: ", en, asDblArray(p)) == RTNORM)
- {
- AcDbObjectId idCurve; acdbGetObjectId(idCurve, en);
- AcDbObjectPointer<AcDbCurve> pCurve(idCurve, AcDb::kForRead);
- if ((es = pCurve.openStatus()) != Acad::eOk)
- {
- acutPrintf(L"\nОшибка открытия кривой: %s", acadErrorStatusText(es));
- return;
- }
- AcGeDoubleArray pts;
- AcGePoint3d pNear = p; pCurve->getClosestPointTo(p, pNear);
- AcDbPoint *pDbPoint = new AcDbPoint(pNear);
- pDbPoint->setDatabaseDefaults();
- postToDwg(pDbPoint);
- pDbPoint->close();
- if (es == Acad::eOk)
- {
- AcDbCircle *pCircle = new AcDbCircle(p, AcGeVector3d::kZAxis, radius);
- AcGePlane plane(p, AcGeVector3d::kZAxis);
- AcGePoint3dArray ptsInts;
- pCurve->intersectWith(pCircle, AcDb::kOnBothOperands, plane, ptsInts);
- delete pCircle;
- if (ptsInts.length() >= 2)
- {
- AcGePoint3d ptFirst = ptsInts[0], ptLast = ptsInts[ptsInts.length() - 1];
- pCurve->getClosestPointTo(ptsInts[0], ptFirst);
- pCurve->getClosestPointTo(ptsInts[ptsInts.length() - 1], ptLast);
- double paramFirst = 0, paramLast = 0;
- pCurve->getParamAtPoint(ptFirst, paramFirst);
- pCurve->getParamAtPoint(ptLast, paramLast);
- if (paramFirst > paramLast)
- {
- pts.append(paramLast);
- pts.append(paramFirst);
- }
- else
- {
- pts.append(paramFirst);
- pts.append(paramLast);
- }
- }
- else
- {
- double param = 0; pCurve->getParamAtPoint(pNear, param);
- pts.append(param);
- }
- }
- else
- {
- double param = 0;
- pCurve->getParamAtPoint(pNear, param);
- pts.append(param);
- }
- AcDbVoidPtrArray aSegs;
- if ((es = pCurve->getSplitCurves(pts, aSegs)) != Acad::eOk)
- {
- acutPrintf(L"\npCurve->getSplitCurves: %s", acadErrorStatusText(es));
- return;
- }
- if (aSegs.length() > 1)
- {
- AcDbEntity *pEnt = reinterpret_cast<AcDbEntity *>(aSegs[0]);
- if (postToDwg(pEnt) == Acad::eOk)
- pEnt->close();
- else
- delete pEnt;
- pEnt = reinterpret_cast<AcDbEntity *>(aSegs[aSegs.length() - 1]);
- if (postToDwg(pEnt) == Acad::eOk)
- pEnt->close();
- else
- delete pEnt;
- // Освобождаем память вырезанных сегментов
- for (int i = 1; i < aSegs.length() - 1; i++)
- {
- AcDbEntity *pEnt = reinterpret_cast<AcDbEntity *>(aSegs[i]);
- delete pEnt;
- }
- // Удаляем исходную кривую
- if (pCurve->upgradeOpen() == Acad::eOk)
- pCurve->erase();
- }
- }
- }
- };
- //-----------------------------------------------------------------------------
- IMPLEMENT_ARX_ENTRYPOINT(CBreakLineApp)
- ACED_ARXCOMMAND_ENTRY_AUTO(CBreakLineApp, Rivilis, BreakLine, BreakLine, ACRX_CMD_MODAL, NULL)
Так выглядит работа этого кода:
Автор: Александр Ривилис
Обсуждение: http://adn-cis.org/forum/index.php?topic=
Опубликовано 01.08.2018