明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4278|回复: 1

使用梦想绘图控件ARX编程,搜索闭合区域,计算面积和周长的代码

[复制链接]
发表于 2009-9-23 08:31:00 | 显示全部楼层 |阅读模式

程序运效果可以参考控件安装目录的sample\edit.sln工程。

.h 文件
// 计算直线与PL线组成的闭合区域的面积,和周长。

class CAreaCalculation
{
public:
CAreaCalculation(void);
virtual ~CAreaCalculation(void);

// 执行该功能。
void Do();

private:
// 跟用户交互,让用户在图上选择一个闭合区域的直线或PL线。
AcDbObjectId SelEntity();


// 搜索闭合区域的递归调用函数。
bool SearchClosePathCall(IN AcGePoint3d startPt, // 搜索的开始点。
IN AcGePoint3d curPt, // 当前搜索位置。
IN std::set<AcDbObjectId>& adyFindId, // 搜索过程中,已经发现的曲线ID.
IN OUT std::vector<AcDbObjectId>& aryPathId, // 搜索成功,返回的闭合区域ID。
IN double dSearchTol, // 搜索精度范围,在这个范围内的曲线是认为连接的。
IN struct resbuf* pRbFilter // 搜索实体的过滤条件。
);

};


.cpp文件:

#include "StdAfx.h"
#include "AreaCalculation.h"
#include "MxTools.h"

CAreaCalculation::CAreaCalculation(void)
{
}

CAreaCalculation::~CAreaCalculation(void)
{
}


void CAreaCalculation::Do()
{
MxDraw::StopAllTwinkeEnt(MxDraw::GetCurOcxHandle() );
// 让用户选择闭合区域中的某条线,然后由该条线搜索到整个闭合区域。
AcDbObjectId entId = CAreaCalculation::SelEntity();
if(entId.isNull() )
return;

// 由entId实体开始,搜索整个闭合区域。
AcDbObjectPointer<AcDbCurve> spCurve(entId,AcDb::kForRead);
if(spCurve.openStatus() != Acad::eOk)
{
ASSERT(0);
return ;
}

AcGePoint3d sPt;
spCurve->getStartPoint(sPt);

AcGePoint3d ePt;
spCurve->getEndPoint(ePt);

double dSeachTol = 3.0;


AcDbPolyline *pPl = AcDbPolyline::cast(spCurve.object() );
if(pPl != NULL)
{
bool isClose = pPl->isClosed();
if(!isClose)
{
// 看该曲线是不是首尾相连的.
if(sPt.distanceTo(ePt) < dSeachTol)
isClose = true;
}
if(isClose)
{
double dArea = 0.0;
pPl->getArea(dArea);

double dEndParam = 0.0;
pPl->getEndParam(dEndParam);

double dLen = 0.0;
pPl->getDistAtParam(dEndParam,dLen);

acutPrintf(_T("\n 面积为:%lf,周长为:%lf"),dArea,dLen);

spCurve->close();
MxDraw::TwinkeEnt(entId);
return ;
}
}


CString sLayerName = spCurve->layerEx();

spCurve->close();


if(sPt.distanceTo(ePt) < dSeachTol)
{
// 小短线。
acutPrintf(_T("\n 选择的曲线开始点与结束点相同"));
return ;
}

std::set<AcDbObjectId> adyFindId;
adyFindId.insert(entId);

// 把层名做为过滤条件。
struct resbuf* pRbFilter = acutBuildList(RTDXF0,_T("LINE,LWPOLYLINE,ARC"),8,sLayerName,0);

std::vector<AcDbObjectId> aryPathId;
if(!SearchClosePathCall(sPt,
ePt,adyFindId,aryPathId,dSeachTol,pRbFilter) )
{
acutPrintf(_T("\n 没有发现闭合区域"));
acutRelRb(pRbFilter);
return ;
}
acutRelRb(pRbFilter);
aryPathId.push_back(entId);


// 由闭合区域,构造一个临时的PL线,用于计算面积。

std::vector<AcDbObjectId>::reverse_iterator iter = aryPathId.rbegin();
bool isFirst = false;

AcGePoint3d curPt = sPt;
std::vector<AcGePoint2d> vecVertex;
std::vector<double> vecBulge;

vecVertex.push_back(sPt.convert2d(AcGePlane::kXYPlane));
vecBulge.push_back(0.0);
for(;iter != aryPathId.rend();++iter)
{
AcDbObjectPointer<AcDbCurve> spCurve(*iter,AcDb::kForRead);
if(spCurve.openStatus() != Acad::eOk)
{
ASSERT(0);
return ;
}
if(AcDbLine::cast(spCurve.object() ) != NULL)
{
AcDbLine* pLine = AcDbLine::cast(spCurve.object());
AcGePoint3d sPt;
pLine->getStartPoint(sPt);

AcGePoint3d ePt;
pLine->getEndPoint(ePt);

AcGePoint3d nextPt = sPt;
if(curPt.distanceTo(sPt) < curPt.distanceTo(ePt) )
nextPt = ePt;

vecVertex.push_back(nextPt.convert2d(AcGePlane::kXYPlane));
vecBulge.push_back(0.0);

curPt = nextPt;
}
else if(AcDbArc::cast(spCurve.object()) != NULL)
{
AcDbArc* pArc = AcDbArc::cast(spCurve.object());
AcGePoint3d sPt;
pArc->getStartPoint(sPt);

AcGePoint3d ePt;
pArc->getEndPoint(ePt);

if(curPt.distanceTo(sPt) > curPt.distanceTo(ePt) )
{
AcGePoint3d tmpPt = sPt;
sPt = ePt;
ePt = tmpPt;
}
curPt = ePt;

double dSParam = 0.0;
double dEParam = 1.0;
pArc->getStartParam(dSParam);
pArc->getEndParam(dEParam);

AcGePoint3d cenPt;
if(pArc->getPointAtParam(dSParam + (dEParam - dSParam) / 2.0,cenPt)
!= Acad::eOk)
{
ASSERT(0);
return;
}

// 计算圆弧的凸度。
double dBulge = 0.0;
if(MxTools::GetArcBulge(sPt,
cenPt,
ePt,
dBulge
) )
{
vecBulge[vecBulge.size() - 1] = dBulge;
vecVertex.push_back(ePt.convert2d(AcGePlane::kXYPlane));
vecBulge.push_back(0.0);
}
else
{
vecVertex.push_back(ePt.convert2d(AcGePlane::kXYPlane));
vecBulge.push_back(0.0);
}
}
else if(AcDbPolyline::cast(spCurve.object()) != NULL)
{
AcDbPolyline* pPolyline = AcDbPolyline::cast(spCurve.object());


std::vector<McGePoint2d> vecTmpPt;
std::vector<double> vecTmpBulge;

int iNum = pPolyline->numVerts();
for(int k = 0; k < iNum;k++)
{
AcGePoint2d pt;
pPolyline->getPointAt(k,pt);
double dBulge = 0.0;
pPolyline->getBulgeAt(k,dBulge);

vecTmpPt.push_back(pt);
vecTmpBulge.push_back(dBulge);
}

if(curPt.convert2d(AcGePlane::kXYPlane).distanceTo(vecTmpPt[0])
> curPt.convert2d(AcGePlane::kXYPlane).distanceTo(vecTmpPt[iNum - 1])
)
{
// 反向。
for(int j = iNum - 2; j >= 0 ;j--)
{
vecBulge[vecBulge.size() - 1] = -vecTmpBulge[j];
vecVertex.push_back(vecTmpPt[j]);
vecBulge.push_back(0.0);
}
curPt = vecTmpPt[0].Point3d();
}
else
{
//
for(int j = 1; j < iNum;j++)
{
vecBulge[vecBulge.size() - 1] = vecTmpBulge[j - 1];
vecVertex.push_back(vecTmpPt[j]);
vecBulge.push_back(0.0);
}
curPt = vecTmpPt[iNum - 1].Point3d();;
}
}
else
{
ASSERT(0);
}
}

// 构建PL线.

ASSERT(vecVertex.size() == vecBulge.size());

AcDbPolyline tmpPl;
for(unsigned int n = 0; n < vecVertex.size();n++)
{
tmpPl.addVertexAt(vecVertex[n],vecBulge[n]);
}

// 调用tmpPL计算面积,周长,函数。

double dArea = 0.0;
tmpPl.getArea(dArea);

double dEndParam = 0.0;
tmpPl.getEndParam(dEndParam);

double dLen = 0.0;
tmpPl.getDistAtParam(dEndParam,dLen);

acutPrintf(_T("\n 面积为:%lf,周长为:%lf"),dArea,dLen);

for(unsigned int nn = 0; nn < aryPathId.size();nn++)
{
MxDraw::TwinkeEnt(aryPathId[nn]);
}

}

bool CAreaCalculation::SearchClosePathCall(IN AcGePoint3d startPt,
IN AcGePoint3d curPt,
IN std::set<AcDbObjectId>& adyFindId,
IN OUT std::vector<AcDbObjectId>& aryPathId,
IN double dSearchTol,
IN struct resbuf* pRbFilter
)
{

AcDbObjectIdArray aryId;
if(!MxTools::FindEntAtPoint(curPt,pRbFilter,
dSearchTol * 10.0,aryId) )
{
return false;
}

// vecNextPos 需要搜索的下一个位置。
std::map<AcDbObjectId,AcGePoint3d> mapNextPos;
for(int i = 0; i < aryId.length();i++)
{
if(adyFindId.find(aryId) != adyFindId.end() )
continue;

AcDbObjectPointer<AcDbCurve> spCurve(aryId,AcDb::kForRead);
if(spCurve.openStatus() != Acad::eOk)
continue;

AcGePoint3d sPt;
spCurve->getStartPoint(sPt);

AcGePoint3d ePt;
spCurve->getEndPoint(ePt);

// 小短线。
if(sPt.distanceTo(ePt) < dSearchTol)
{
continue;
}
double dSDis = sPt.distanceTo(curPt);
double dEDis = ePt.distanceTo(curPt);
double dMinDis = dSDis;
if(dMinDis > dEDis)
dMinDis = dEDis;
if(dMinDis > dSearchTol)
{
// 认为两条线不连接.
continue;
}
adyFindId.insert(aryId);


AcGePoint3d nexPt = sPt;
if(dSDis < dEDis )
nexPt = ePt;

if(nexPt.distanceTo(startPt) < dSearchTol)
{
// 找到了闭合区域。
aryPathId.push_back(aryId);
return true;
}
mapNextPos.insert(std::make_pair(aryId,nexPt) );
}

std::map<AcDbObjectId,AcGePoint3d>::iterator iter = mapNextPos.begin();
for(;iter != mapNextPos.end();++iter)
{
if(SearchClosePathCall(startPt,
iter->second,
adyFindId,
aryPathId,
dSearchTol,pRbFilter
) )
{
aryPathId.push_back(iter->first);
return true;
}
}
return false;
}

AcDbObjectId CAreaCalculation::SelEntity()
{
struct resbuf* pRbFilter = acutBuildList(RTDXF0,_T("LINE,LWPOLYLINE,ARC"),0);

AcDbObjectId id;
AcGePoint3d ptPick;

if(MxTools::SelectEnt(_T("\n 选择闭合区域中的某条线:"),pRbFilter,id,ptPick) != RTNORM)
{
return id;
}
acutRelRb(pRbFilter);

return id;
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2010-8-13 17:47:00 | 显示全部楼层

我只想问下,你是如何把CAD嵌入到自己的窗体中的~~~~~

 

谢谢了

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 13:00 , Processed in 0.174192 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表