It happend when offsetting spline. But it's ok when offsetting line, polyline, circle and arc. Any ideas! Thanks.
ads_point pt;
ads_name ename;
if (acedEntSel(NULL, ename, pt) != RTNORM) return;
AcDbObjectId id;
acdbGetObjectId(id, ename);
AcDbEntityPointer pent(id, AcDb::kForRead);
pent.openStatus();
AcDbCurve* psp = AcDbCurve::cast(pent);
if (psp == NULL) return;
AcGeCurve3d* pGeCurve = NULL;
psp->getAcGeCurve(pGeCurve);
pent->close();
double offsetdist = 100.0;
AcGeVoidPointerArray arr;
pGeCurve->getTrimmedOffset(offsetdist, AcGeVector3d::kZAxis, arr, AcGe::kExtend);
delete pGeCurve;
pGeCurve = NULL;
AcAxDocLock lock;
for (int i = 0; i < arr.length(); ++i) {
AcGeCurve3d* pCurve = (AcGeCurve3d*)arr.at(i);
AcDbCurve* pNewcurve = NULL;
AcDbCurve::createFromAcGeCurve(*pCurve, (AcDbCurve*&)pNewcurve);
delete pCurve;
pNewcurve->setColorIndex(1);
{
// append to database
AcDbDatabase* pdb = acdbHostApplicationServices()->workingDatabase();
AcDbObjectId curid = pdb->currentSpaceId();
AcDbBlockTableRecordPointer pbtr(curid, AcDb::kForWrite);
pbtr.openStatus();
AcDbObjectId newid;
pbtr->appendAcDbEntity(newid, pNewcurve);
}
pNewcurve->close();
}
Solved! Go to Solution.
Solved by tbrammer. Go to Solution.
The problem is that AcDbCurve::createFromAcGeCurve(*pCurve, pNewcurve) returns eInvalidInput for (some?) splines and leaves pNewcurve==NULL. You should always check the Acad::ErrorStatus!
Here is a possible workaround:
void cmdTestOffsetSpline()
{
ads_point pt;
ads_name ename;
if (acedEntSel(NULL, ename, pt) != RTNORM)
return;
AcDbObjectId id;
acdbGetObjectId(id, ename);
AcDbEntityPointer pent(id, AcDb::kForRead);
pent.openStatus();
AcDbCurve* psp = AcDbCurve::cast(pent);
if (psp == NULL) return;
AcGeCurve3d* pGeCurve = NULL;
Acad::ErrorStatus es = psp->getAcGeCurve(pGeCurve); //TB check ErrorStatus!
pent->close();
if (es || !pGeCurve) { //TB check ErrorStatus!
acutPrintf(L"\ngetAcGeCurve(crv)=%s, crv=%x", acadErrorStatusText(es), pGeCurve);
return;
}
double offsetdist = 100.0;
AcGeVoidPointerArray arr;
pGeCurve->getTrimmedOffset(offsetdist, AcGeVector3d::kZAxis, arr, AcGe::kExtend);
delete pGeCurve;
pGeCurve = NULL;
AcAxDocLock lock;
for (int i = 0; i < arr.length(); ++i) {
AcGeCurve3d* pCurve = (AcGeCurve3d*)arr.at(i);
if (!pCurve)
continue;
AcGe::EntityId type = pCurve->type();
AcDbCurve* pNewcurve = NULL;
es = AcDbCurve::createFromAcGeCurve(*pCurve, pNewcurve);
if (!es) //TB check es! eInvalidInput is returned for splines!
delete pCurve;
else {
if (type == AcGe::kCompositeCrv3d) {
AcGeNurbCurve3d* pFinalNurb = NULL;
AcGePoint3d ptNurbEnd, ptEnd, ptStart;
AcGeCompositeCurve3d *ccrv = (AcGeCompositeCurve3d*)pCurve;
AcGeVoidPointerArray curveList;
ccrv->getCurveList(curveList);
for (void* vp : curveList)
{
AcGeNurbCurve3d *pNurb = NULL, *pTmpNurb = NULL;
AcGeCurve3d* crv = (AcGeCurve3d*)vp;
type = crv->type();
if (type != AcGe::kNurbCurve3d) {
double epsilon = AcGeContext::gTol.equalPoint();
pTmpNurb = pNurb = new AcGeNurbCurve3d(*crv, epsilon);
}
else
pNurb = (AcGeNurbCurve3d*)crv;
if (!pFinalNurb) {
pFinalNurb = pNurb;
if (!pTmpNurb)
crv = NULL; // don't delete crv!
}
else {
if (pNurb->hasStartPoint(ptStart) && (ptStart==ptNurbEnd)) {
pFinalNurb->joinWith(*pNurb);
if (pFinalNurb->hasEndPoint(ptEnd))
ptNurbEnd = ptEnd;
}
}
if (pFinalNurb->hasEndPoint(ptEnd))
ptNurbEnd = ptEnd;
if (crv)
delete crv;
}
if (pFinalNurb) {
AcDbCurve* segment=NULL;
es = AcDbCurve::createFromAcGeCurve(*pFinalNurb, pNewcurve);
delete pFinalNurb;
}
}
}
if (pNewcurve) {
AcDbDatabase* pdb = acdbHostApplicationServices()->workingDatabase();
pNewcurve->setDatabaseDefaults(pdb);
pNewcurve->setColorIndex(1); {
// append to database
AcDbObjectId curid = pdb->currentSpaceId();
AcDbBlockTableRecordPointer pbtr(curid, AcDb::kForWrite);
pbtr.openStatus();
AcDbObjectId newid;
pbtr->appendAcDbEntity(newid, pNewcurve);
}
pNewcurve->close();
}
}
}
I played a bit with the function using epsilon=0.1 which reduces the number of control points. But the resulting spline causes a crash in AcDbCurve::createFromAcGeCurve(*pCurve, pNewcurve) if I try to apply an offset to it.
This looks like a bug in AutoCAD. The drawing I used is attached. I started with the black spline. With epsilon=0.1 the function created the red spline. This in turn caused a crash. Everything seems to be fine with the red spline.
Thanks for your reply, tbrammer. Your code is very enlightened to me.
I tested on some random drawed spline in AutoCAD 2020. The first "AcDbCurve::createFromAcGeCurve" just crashed, not return anything like eInvalidInput.
Another thing in my case is that the type of AcGeCurve3d after "getTrimmedOffset" is always kOffsetCurve3d, and constructing a AcGeNurbCurve3d from AcGeOffsetCurve3d crashed also.
I'll try it again with a higher AutoCAD version.
That's exactly what I found in my tests with AutoCAD 2022. But I haven't tested with 2023.
I suppose there is a severe bug with spline offset curves. Autodesk engineers should have a look at this.
Can't find what you're looking for? Ask the community or share your knowledge.