直线和多段线的识别与提取
实现步骤:
1.获取一个图层所有的直线与封闭的多线段,并保存记录其Id
2.读取实体对应的属性,并使用一个数组保存筛选出来符合条件的实体Id
3.创建新图层,将实体设置在对应的新图层中
具体代码如下:
首先写一个过滤图层实体的函数,返回值为保存符合条件的实体Id数组
/**
@bref:过滤图层直线和多线段
@param 图层名
@return 实体Id数组
**/
AcDbObjectIdArray GetAllEntityIds(TCHAR * layerName)
{
AcDbObjectIdArray entIds; //满足条件的实体集合
bool bFilterLayer = false; //是否需要过滤图层
Acad::ErrorStatus es; //操作判断
AcDbObjectId layerId;
if (layerName != NULL)
{
AcDbLayerTable * pLayerTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForRead);
if (!pLayerTbl->has(layerName)) //判断当前图形中是否包含指定图层
{
pLayerTbl->close();
return entIds;
}
es = pLayerTbl->getAt(layerName, layerId);
pLayerTbl->close();
if (es != Acad::eOk)
{
return entIds;
}
bFilterLayer = true;
}
//获得块表
AcDbBlockTable *pBlkTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForRead);
//获取模型的块记录表
AcDbBlockTableRecord *pBlkTblRcd = NULL;
es = pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead);
pBlkTbl->close();
if (es != Acad::eOk)
{
return entIds;
}
//创建遍历器
AcDbBlockTableRecordIterator *it = NULL;
pBlkTblRcd->newIterator(it);
for (it->start(); !it->done(); it->step())
{
AcDbEntity *pEnt = NULL;
es = it->getEntity(pEnt, AcDb::kForRead); //打开实体
if (es == Acad::eOk)
{
//过滤多线段
if (pEnt->isKindOf(AcDbPolyline::desc())|| pEnt->isKindOf(AcDbLine::desc()))
{
if (bFilterLayer)
{
if (pEnt->layerId() == layerId) //本图层
{
entIds.append(pEnt->objectId());
}
}
else
{
entIds.append(pEnt->objectId()); // 如果不需要对图层进行过滤,直接加上去
}
}
pEnt->close();
}
else
{
acutPrintf(TEXT("\n打开实体失败(错误代码:%d)."),(int)es);
}
}
delete it; //删除迭代器
pBlkTblRcd->close();
return entIds;
}
对符合条件的实体进行筛选,分别对从图层获取的线和多段线进行条件判断,多段线是当初始点的坐标差小于10时,或者符合isClosed()条件的判断其为封闭,代码片段如下
AcDbObjectIdArray entIds = GetAllEntityIds(LayerName);
//acutPrintf(TEXT("图层中多线段的数目是:%d\n"), entIds.length());
AcDbObjectIdArray newIds;
for (int i = 0; i < entIds.length(); i++)
{
AcDbPolyline *ePoly = NULL;
AcDbLine *eLine = NULL;
if(acdbOpenObject(ePoly, entIds[i],AcDb::kForRead)== Acad::eOk)
{
if (ePoly->isClosed())
{
newIds.append(entIds[i]);
}
else
{
int num = ePoly->numVerts();
AcGePoint3d startPoint;
AcGePoint3d endPoint;
ePoly->getPointAt(0, startPoint);
ePoly->getPointAt(num - 1, endPoint);
if (startPoint.x-endPoint.x <10 && startPoint.y - endPoint.y <10)
{
newIds.append(entIds[i]);
ePoly->close();
}
}
}
else if (acdbOpenObject(eLine, entIds[i], AcDb::kForRead) == Acad::eOk)
{
newIds.append(entIds[i]);
eLine->close();
}
else
{
delete ePoly;
delete eLine;
}
}
创建图层,获取当前图层的Id,如果以及存在,则不需要新建,获取图层Id的代码如下:
/**
@brief 获取图层的Id
@param 图层名
@return AcDbObjectId
**/
AcDbObjectId GetLayerId(const TCHAR* layerName)
{
assert(layerName != NULL); //判断输入非空
AcDbLayerTable *pLayerTbl;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForRead); //打开图层表
AcDbObjectId layerId = AcDbObjectId::kNull;
if (pLayerTbl->has(layerName))
{
pLayerTbl->getAt(layerName, layerId);
}
pLayerTbl->close();
return layerId;
}
创建图层代码如下:
/**
@brief 创建一个图层
@param1 layerName
@param2 图层颜色
**/
void Add(const TCHAR* layerName, int colorIndex)
{
assert(layerName != NULL);
assert(colorIndex >= 1 && colorIndex <= 255);
// 获得层表
AcDbLayerTable *pLayerTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForWrite);
// 是否已经存在同名的层
if (!pLayerTbl->has(layerName))
{
AcDbLayerTableRecord *pLayerTblRcd = new AcDbLayerTableRecord();
pLayerTblRcd->setName(layerName);
AcCmColor color;
color.setColorIndex(colorIndex);
pLayerTblRcd->setColor(color);
Acad::ErrorStatus es = pLayerTbl->add(pLayerTblRcd);
pLayerTblRcd->close();
}
pLayerTbl->close();
}
对输入的图层名进行判断,是否需要新建图层
// 提示用户输入图层名称
TCHAR layerName[100];
if (acedGetString(Adesk::kFalse, TEXT("\n输入图层的名称:"), layerName) != RTNORM)
{
return;
}
// 新建图层
AcDbObjectId layerId = CLayerUtil::GetLayerId(layerName);
if (layerId.isValid())
{
acutPrintf(TEXT("\n图形中已经存在同名的图层."));
}
else
{
CLayerUtil::Add(layerName);
acutPrintf(TEXT("\n成功创建图层."));
}
将筛选的实体放入指定图层,代码片段如下:
if (newIds.length() != 0)
{
for (int i = 0; i < newIds.length(); i++)
{
AcDbPolyline *poly = NULL;
AcDbLine *pLine = NULL;
if (acdbOpenObject(poly, newIds[i], AcDb::kForWrite) == Acad::eOk)
{
poly->setLayer(layerId);
poly->setLayer(LayerName);
poly->close();
}
else if (acdbOpenObject(pLine, newIds[i], AcDb::kForWrite) == Acad::eOk)
{
pLine->setLayer(layerId);
pLine->setLayer(LayerName);
pLine->close();
}
else
{
delete poly;
delete pLine;
}
}
}
代码展示:
void getAllClosed(TCHAR * LayerName)
{
AcDbObjectIdArray entIds = GetAllEntityIds(LayerName);
acutPrintf(TEXT("图层中多线段的数目是:%d\n"), entIds.length());
AcDbObjectIdArray newIds;
for (int i = 0; i < entIds.length(); i++)
{
AcDbPolyline *ePoly = NULL;
AcDbLine *eLine = NULL;
if(acdbOpenObject(ePoly, entIds[i],AcDb::kForRead)== Acad::eOk)
{
if (ePoly->isClosed())
{
newIds.append(entIds[i]);
}
else
{
int num = ePoly->numVerts();
AcGePoint3d startPoint;
AcGePoint3d endPoint;
ePoly->getPointAt(0, startPoint);
ePoly->getPointAt(num - 1, endPoint);
if (startPoint.x-endPoint.x <10 && startPoint.y - endPoint.y <10)
{
newIds.append(entIds[i]);
ePoly->close();
}
}
}
else if (acdbOpenObject(eLine, entIds[i], AcDb::kForRead) == Acad::eOk)
{
newIds.append(entIds[i]);
eLine->close();
}
else
{
delete ePoly;
delete eLine;
}
}
acutPrintf(TEXT("图层中封闭多线段的数目是:%d\n"), newIds.length());
//添加图层
// 提示用户输入图层名称
TCHAR layerName[100];
if (acedGetString(Adesk::kFalse, TEXT("\n输入图层的名称:"), layerName) != RTNORM)
{
return;
}
// 新建图层
AcDbObjectId layerId = GetLayerId(layerName);
if (layerId.isValid())
{
acutPrintf(TEXT("\n图形中已经存在同名的图层."));
}
else
{
Add(layerName);
acutPrintf(TEXT("\n成功创建图层."));
}
AcDbBlockTable *pBlkTbl = NULL;
AcDbBlockTableRecord *pBlkRcd = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForRead);
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkRcd, AcDb::kForWrite);
pBlkTbl->close();
AcDbLayerTable *pLayeTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayeTbl, AcDb::kForRead);
AcDbLayerTableRecord *pLayerTblRcd = NULL;
pLayeTbl->getAt(layerName, layerId);
pLayeTbl->close();
if (acdbOpenObject(pLayerTblRcd, layerId, AcDb::kForWrite) == Acad::eOk)
{
if (newIds.length() != 0)
{
for (int i = 0; i < newIds.length(); i++)
{
AcDbPolyline *poly = NULL;
AcDbLine *pLine = NULL;
if (acdbOpenObject(poly, newIds[i], AcDb::kForWrite) == Acad::eOk)
{
poly->setLayer(layerId);
poly->setLayer(LayerName);
poly->close();
}
else if (acdbOpenObject(pLine, newIds[i], AcDb::kForWrite) == Acad::eOk)
{
pLine->setLayer(layerId);
pLine->setLayer(LayerName);
pLine->close();
}
else
{
delete poly;
delete pLine;
}
}
}
pLayerTblRcd->close();
}
else
{
delete pLayerTblRcd;
}
pBlkRcd->close();
}
至此,全部步骤完成,在实体创建以及块表创建中需要注意关闭实体,也可以使用智能指针模板进行管理,可以减少不必要的代码debug过程,代码比较粗糙,请见谅!欢迎前来交流