样条曲线拟合
//定义PI
#ifndef PI
#define PI 4*atan(1.0)//提高pi的精度
#endif
bool getSplineSamplePoints(AcDbSpline *&spline, AcGePoint3dArray &pnts)
{
assert(spline != NULL);
AcGePoint3d orgPt;
spline->getStartPoint(orgPt);
pnts.append(orgPt);
double dStartParam=0.0;
spline->getStartParam(dStartParam);
double dEntParam=0.0;
spline->getEndParam(dEntParam);
double dDist=0.0;
spline->getDistAtParam(dEntParam,dDist);
int nNum=(int)dDist/0.005;
if(nNum<25)
{
nNum=25;
}
if(nNum>10000)
{
nNum=10000;
}
for(int i=0;i<nNum;i++)
{
double dTmpParam=0.0;
spline->getParamAtDist(dDist*(i+1)/nNum,dTmpParam);
spline->getPointAtParam(dTmpParam,orgPt);
pnts.append(orgPt);
}
return pnts.logicalLength()>2;
}
AcGePoint2d convert3dPointTo2d(AcGePoint3d pt)
{
AcGePoint2d pm;
pm.set(pt.x,pt.y);
return pm;
}
//获取三个点构成的夹角
double GetIntersectionDngle(AcGePoint2d pt1,AcGePoint2d pt2,AcGePoint2d pt3)
{
AcGeVector2d vt1=pt1-pt2;
AcGeVector2d vt2=pt3-pt2;
return vt1.angleTo(vt2);
}
//获取三个点构成的夹角
double GetIntersectionDngle(AcGePoint3d pt1,AcGePoint3d pt2,AcGePoint3d pt3)
{
return GetIntersectionDngle(convert3dPointTo2d(pt1),convert3dPointTo2d(pt2),convert3dPointTo2d(pt3));
}
//删除构成直线的三个点中间的点
//dMinAngle,构成的夹角最小值,默认为0.5度
void RemovePointBetweenLine(AcGePoint3dArray &pnts,double dMinAngle=PI-0.5*PI/180.0)
{
AcGePoint3dArray rcPts;
if(pnts.logicalLength()<=2)
{
return;
}
rcPts.append(pnts.at(0));
rcPts.append(pnts.at(1));
for(int i=2;i<pnts.logicalLength();i++)
{
AcGePoint3d pt1=rcPts.at(rcPts.logicalLength()-2);
AcGePoint3d pt2=rcPts.at(rcPts.logicalLength()-1);
AcGePoint3d pt3=pnts.at(i);
double dAngle=GetIntersectionDngle(pt1,pt2,pt3);
if(dAngle>=dMinAngle&&dAngle<=PI)
{
rcPts.setAt(rcPts.logicalLength()-1,pt3);
}
else
{
rcPts.append(pt3);
}
}
pnts.setLogicalLength(0);
pnts.append(rcPts);
}
// 功能:将选择集转换为实体ID数组
// 参数: ssName,选择集
// ObjIds,实体ID数组
// 返回:
void SSToIds(AcDbObjectIdArray& ObjIds,ads_name ssName)
{
AcDbObjectId ObjId;
ads_name EntName;
long nLength=0;
acedSSLength(ssName,&nLength);
for(int nLen=0; nLen<nLength; nLen++)
{
acedSSName(ssName,nLen,EntName);
acdbGetObjectId(ObjId,EntName);
ObjIds.append(ObjId);
}
}
// 功能:添加实体到块表记录中
// 参数: pEnt:待添加的实体指针
// btrID,AcDbBlockTableRecord的ID
// 返回: 实体的ObjectID,如果插入失败返回一个空的ObjectId
AcDbObjectId AppendEntity(AcDbEntity* pEnt,const AcDbObjectId btrID)
{
AcDbObjectId resultId;
resultId.setNull();
AcDbBlockTableRecord* pBlkRec = NULL;//打开表
Acad::ErrorStatus es = acdbOpenObject(pBlkRec, btrID, AcDb::kForWrite);
if (es != Acad::eOk)
{
acutPrintf(_T(“
打开模型空间失败!%s”),acadErrorStatusText(es));
return resultId;
}
es = pBlkRec->appendAcDbEntity(resultId,pEnt);//添加实体
if (es != Acad::eOk)
{
acutPrintf(_T(“
添加对象到模型空间失败!%s”),acadErrorStatusText(es));
pBlkRec->close();
return resultId;
}
es=pBlkRec->close();
return resultId;
}
Acad::ErrorStatus ToPLine(AcDbSpline *spline)
{
AcGePoint3dArray pnts;
bool rc=getSplineSamplePoints(spline,pnts);
if(!rc)
return Acad::eInvalidInput;
RemovePointBetweenLine(pnts);
AcDbPolyline* pLine=new AcDbPolyline(pnts.logicalLength());
for(int i=0;i<pnts.logicalLength();i++)
{
pLine->addVertexAt(i,convert3dPointTo2d(pnts.at(i)));
}
AppendEntity(pLine,spline->blockId());
pLine->close();
return Acad::eOk;
}
Acad::ErrorStatus ToPLine(AcDbObjectId id)
{
AcDbObjectPointer<AcDbSpline> spLine(id,AcDb::kForRead);
if(spLine.openStatus()!=Acad::eOk)
return spLine.openStatus();
return ToPLine(spLine.object());
}
void ToPLine()
{
Acad::ErrorStatus es=eOk;
resbuf* rb = acutBuildList(RTDXF0, _T(“SPLINE”), 0);
ads_name ssName;
acutPrintf(_T(“
请选择样条曲线:
”));
int rc=acedSSGet(NULL, NULL,NULL,rb,ssName);
if(rc!=RTNORM)
{
acutRelRb(rb);
return;
}
AcDbObjectIdArray ids;
SSToIds(ids,ssName);
acedSSFree(ssName);
AcDbObjectId id;
for(int i=0;i<ids.logicalLength();i++)
{
id=ids.at(i);
ToPLine(id);
}
}