- UID
- 786039
- 积分
- 27
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2019-4-11
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2019-4-30 15:50:14
|
显示全部楼层
#include "StdAfx.h"
#include "resource.h"
#include <dbpl.h>
#include <gecomp2d.h>
#include "Common\Document\DwgDatabaseUtil.h"
#include "Common\SortCStringArray\SortCStringArray.h"
//-----------------------------------------------------------------------------
#define szRDS _RXST("GYDL")
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
wchar_t* char2wchar(const char* cchar)
{
wchar_t *m_wchar;
int len = MultiByteToWideChar( CP_ACP ,0,cchar ,strlen( cchar), NULL,0);
m_wchar= new wchar_t[len+1];
MultiByteToWideChar( CP_ACP ,0,cchar,strlen( cchar),m_wchar,len);
m_wchar[len]= '\0';
return m_wchar;
}
// 根据多段线构建二维几何曲线
static bool PolyToGeCurve(AcDbPolyline *pPline, AcGeCurve2d *&pGeCurve)
{
int nSegs; // 多段线的段数
AcGeLineSeg2d line, *pLine; // 几何曲线的直线段部分
AcGeCircArc2d arc, *pArc; // 几何曲线的圆弧部分
AcGeVoidPointerArray geCurves; // 指向组成几何曲线各分段的指针数组
nSegs = pPline->numVerts() - 1;
// 根据多段线创建对应的分段几何曲线
for (int i = 0; i < nSegs; i++)
{
if (pPline->segType(i) == AcDbPolyline::kLine)
{
pPline->getLineSegAt(i, line);
pLine = new AcGeLineSeg2d(line);
geCurves.append(pLine);
}
else if (pPline->segType(i) == AcDbPolyline::kArc)
{
pPline->getArcSegAt(i, arc);
pArc = new AcGeCircArc2d(arc);
geCurves.append(pArc);
}
}
// 处理闭合多段线最后一段是圆弧的情况
if (pPline->isClosed() && pPline->segType(nSegs) == AcDbPolyline::kArc)
{
pPline->getArcSegAt(nSegs, arc);
pArc = new AcGeCircArc2d(arc);
pArc->setAngles(arc.startAng(), arc.endAng() - (arc.endAng() - arc.startAng()) / 100);
geCurves.append(pArc);
}
// 根据分段的几何曲线创建对应的复合曲线
if (geCurves.length() == 1)
{
pGeCurve = (AcGeCurve2d *)geCurves[0];
}
else
{
pGeCurve = new AcGeCompositeCurve2d(geCurves);
}
// 释放动态分配的内存
if (geCurves.length() > 1)
{
for (int i = 0; i < geCurves.length(); i++)
{
delete geCurves[i];
}
}
return true;
}
// 根据指定的一组点创建一个结果缓冲区链表
struct resbuf* BuildRbFromPtArray(const AcGePoint2dArray &arrPoints)
{
struct resbuf *retRb = NULL;
int count = arrPoints.length();
if (count <= 1)
{
acedAlert(TEXT("函数BuildBbFromPtArray中, 点数组包含元素个数不足!"));
return retRb;
}
// 使用第一个点来构建结果缓冲区链表的头节点
ads_point adsPt;
adsPt[X] = arrPoints[0].x;
adsPt[Y] = arrPoints[0].y;
retRb = acutBuildList(RTPOINT, adsPt, RTNONE);
struct resbuf *nextRb = retRb; // 辅助指针
for (int i = 1; i < count; i++) // 注意:不考虑第一个元素,因此i从1开始
{
adsPt[X] = arrPoints[i].x;
adsPt[Y] = arrPoints[i].y;
// 动态创建新的节点,并将其链接到原来的链表尾部
nextRb->rbnext = acutBuildList(RTPOINT, adsPt, RTNONE);
nextRb = nextRb->rbnext;
}
return retRb;
}
// 选择位于多段线内部的所有实体
static bool SelectEntInPoly(AcDbPolyline *pPline, AcDbObjectIdArray &ObjectIdArray, const char *selectMode, double approxEps)
{
// 判断selectMode的有效性
if (_tcscmp(char2wchar(selectMode), TEXT("CP")) != 0 && _tcscmp(char2wchar(selectMode), TEXT("WP")) != 0)
{
acedAlert(TEXT("函数SelectEntInPline中, 指定了无效的选择模式!"));
return false;
}
// 清除数组中所有的ObjectId
/*for (int i = 0; i < ObjectIdArray.length(); i++)
{
ObjectIdArray.removeAt(i);
}*/
ObjectIdArray.removeAll();
AcGeCurve2d *pGeCurve; // 多段线对应的几何曲线
Adesk::Boolean bClosed = pPline->isClosed(); // 多段线是否闭合
if (bClosed != Adesk::kTrue) // 确保多段线作为选择边界时是闭合的
{
pPline->setClosed(!bClosed);
}
// 创建对应的几何类曲线
PolyToGeCurve(pPline, pGeCurve);
// 获得几何曲线的样本点
AcGePoint2dArray SamplePtArray; // 存储曲线的样本点
AcGeDoubleArray ParamArray; // 存储样本点对应的参数值
AcGePoint2d ptStart, ptEnd; // 几何曲线的起点和终点
Adesk::Boolean bRet = pGeCurve->hasStartPoint(ptStart);
bRet = pGeCurve->hasEndPoint(ptEnd);
double valueSt = pGeCurve->paramOf(ptStart);
double valueEn = pGeCurve->paramOf(ptEnd);
AcGeInterval pInterval;
//pGeCurve->getInterval(pInterval, ptStart, ptEnd);
pGeCurve->getInterval(pInterval);
//pInterval.getBounds(ptStart.x, ptEnd.x);
//pInterval.getBounds(ptStart.y, ptEnd.y);
pInterval.getBounds(valueSt, valueEn);
pGeCurve->getSamplePoints(valueSt, valueEn, approxEps, SamplePtArray, ParamArray);
delete pGeCurve; // 在函数PolyToGeCurve中分配了内存
// 确保样本点的起点和终点不重合
AcGeTol tol;
tol.setEqualPoint(0.01);
AcGePoint2d ptFirst = SamplePtArray[0];
AcGePoint2d ptLast = SamplePtArray[SamplePtArray.length() - 1];
if (ptFirst.isEqualTo(ptLast))
{
SamplePtArray.removeLast();
}
// 根据样本点创建结果缓冲区链表
struct resbuf *rb;
rb = BuildRbFromPtArray(SamplePtArray);
//设置过滤条件
/*struct resbuf rbFilter;
TCHAR sbuf[50];
rbFilter.restype = 0;
//_tcscpy(sbuf, TEXT("10kV线路-牧野变"));
_tcscpy(sbuf, TEXT("1"));
rbFilter.resval.rstring = sbuf;
rbFilter.rbnext = NULL;*/
/*struct resbuf *rbFilter;
rbFilter = acutBuildList(
8, TEXT("0,10kV线路-牧野变,10kV线路-平东变,10kV线路-朱庄变,110kV变电站,110kV变电站名称,110kV变电站容量,2020年网格边界,分段开关,联络开关,网格编号,线路编号,线路相连"),
RTNONE);*/
// 使用acedSSGet函数创建选择集
ads_name ssName; // 选择集名称
int rt = acedSSGet(char2wchar(selectMode), rb, NULL, NULL, ssName);
//int rt = acedSSGet(char2wchar(selectMode), rb, NULL, rbFilter, ssName);
//int rt = acedSSGet(char2wchar(selectMode), rb, NULL, &rbFilter, ssName);
if (rt != RTNORM)
{
acutRelRb(rb); // 释放结果缓冲区链表
acedAlert(TEXT("acedSSGet的返回值不等于RTNORM!"));
return false;
}
// 将选择集中所有的对象添加到ObjectIdArray
long length;
acedSSLength(ssName, &length);
for (int i = 0; i < length; i++)
{
// 获得指定元素的ObjectId
ads_name ent;
acedSSName(ssName, i, ent);
AcDbObjectId objId;
acdbGetObjectId(objId, ent);
// 获得指向当前元素的指针
AcDbEntity *pEnt;
Acad::ErrorStatus es = acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
// 选择到作为边界的多段线了,直接跳过该次循环
if (es == Acad::eWasOpenForWrite)
{
continue;
}
ObjectIdArray.append(pEnt->objectId());
pEnt->close();
}
// 释放内存
acutRelRb(rb); // 释放结果缓冲区链表
acedSSFree(ssName); // 删除选择集
return true;
}
/*
该函数的功能及处理思路如下:
一、首先将获取的网格编号放入CStringArray类型的GridNOs
1、根据objectId获取ads_name;
2、根据ads_name获取其所在的图层名;
3、判断图层名中是否含有“网格编号”,如果有,说明该图层中都是网格编号的名字
4、将该图层中都是网格编号的名字写入GridNOs中
二、对GridNOs中网格编号的尾号进行提取并排序
三、生成网格切图的子图文件名称,并通过函数参数输出
*/
void GenerateSubgraphFileName(const AcDbObjectIdArray &InputSubgraphIdArray, CString InputLayerName, CString &OutputSubgraphFileName)
{
if (InputSubgraphIdArray.isEmpty())
{
return;
}
//一、将获取的网格编号放入CStringArray
CStringArray GridNOs;
GridNOs.RemoveAll();
for (int j = 0; j < InputSubgraphIdArray.length(); j++)
{
AcDbObject *ObjPrt;
acdbOpenObject(ObjPrt,InputSubgraphIdArray[j],AcDb::kForRead);
if(ObjPrt->isKindOf(AcDbText::desc()))
{
ads_name objName;
struct resbuf *rbTargEnt;
struct resbuf *rbTrav;
ACHAR lyrName[32];
memset(lyrName,'\0',sizeof(lyrName));
//1、根据objectId获取ads_name
acdbGetAdsName(objName, InputSubgraphIdArray[j]);
//2、根据ads_name获取其所在的图层名
rbTargEnt = acdbEntGet(objName);
if (!rbTargEnt)
{
acutPrintf(_T("\n获取目标实体数据失败!"));
return;
}
rbTrav = rbTargEnt;
while (rbTrav)
{
switch (rbTrav->restype)
{
case 8:
strcpy(reinterpret_cast<char *>(lyrName), reinterpret_cast<const char*>(rbTrav->resval.rstring));
break;
}
rbTrav=rbTrav->rbnext;
}
CString layerName;
layerName.Format(_T("%s"), lyrName);
//3、判断图层名中是否含有“网格编号”,如果有,说明该图层中都是网格编号的名字
//4、将该图层中都是网格编号的名字写入GridNOs中
if(0 <= layerName.Find(InputLayerName))
{
AcDbObject *Obj_Prt;
acdbOpenObject(Obj_Prt, InputSubgraphIdArray[j], AcDb::kForRead);
if(ObjPrt->isKindOf(AcDbText::desc()))
{
//Obj_Prt->close();
AcDbText *pent;
acdbOpenObject(pent, InputSubgraphIdArray[j], AcDb::kForRead);
GridNOs.Add(pent->textString());
pent->close();
}
Obj_Prt->close();
}
}
ObjPrt->close();
}
//二、对GridNOs中网格编号的尾号进行提取并排序
SortCStringArray sortArray;
sortArray.RemoveAll();
if(!GridNOs.IsEmpty())
{
for (int k = 0; k < GridNOs.GetCount(); k++)
{
int lastShortLinePos = GridNOs[k].ReverseFind('-');
sortArray.Add(GridNOs[k].Mid(lastShortLinePos + 1));
}
sortArray.Sort();
}
//三、生成网格切图的子图文件名称,并通过函数参数输出
if(!GridNOs.IsEmpty())
{
OutputSubgraphFileName = GridNOs[0].Left(GridNOs[0].ReverseFind('-') + 1);
for (int m = 0; m < sortArray.GetCount(); m++)
{
OutputSubgraphFileName.Append(sortArray[m]);
OutputSubgraphFileName.Append(_T("、"));
}
OutputSubgraphFileName.Delete(OutputSubgraphFileName.GetLength()-1);
}
}
class CSegmentationByGridApp : public AcRxArxApp {
public:
CSegmentationByGridApp () : AcRxArxApp () {}
virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
// TODO: Load dependencies here
// You *must* call On_kInitAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
// TODO: Add your initialization code here
return (retCode) ;
}
virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
// TODO: Add your code here
// You *must* call On_kUnloadAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
// TODO: Unload dependencies here
return (retCode) ;
}
virtual void RegisterServerComponents () {
}
public:
// - GYDLSegmentationByGrid.dividedByGrid command (do not rename)
static void GYDLSegmentationByGriddividedByGrid(void)
{
// Add your code for command GYDLSegmentationByGrid.dividedByGrid here
//获取当前图层上所有实体的Id
//AcDbObjectIdArray allBorderIds = CDwgDatabaseUtil::GetAllEntityIds(TEXT("图层1"));
//AcDbObjectIdArray allBorderIds = CDwgDatabaseUtil::GetAllEntityIds(TEXT("网格边界"));
//AcDbObjectIdArray allBorderIds = CDwgDatabaseUtil::GetAllEntityIds(TEXT("0"));
//AcDbObjectIdArray allBorderIds = CDwgDatabaseUtil::GetAllEntityIds(TEXT("LS——供电单元"));
AcDbObjectIdArray allBorderIds = CDwgDatabaseUtil::GetAllEntityIds(TEXT("2020年网格边界"));
//获取当前dwg文件的图形数据库
AcDbDatabase *pSourceDb = acdbHostApplicationServices()->workingDatabase();
//创建分图的图形数据库
AcDbDatabase *pSubgraphDestDb = NULL;
//建立多段线网格边界的圈交(CP)模式选择集数组
AcDbObjectIdArray subgraphIdArray;
for (int i = 0; i < allBorderIds.length(); i++)
{
AcDbPolyline *pPolyline = NULL;
if (acdbOpenObject(pPolyline, allBorderIds[i], AcDb::kForWrite) == Acad::eOk)
{
//获取每个多段线网格边界的圈交(CP)模式选择集的Id
SelectEntInPoly(pPolyline, subgraphIdArray, "CP", 1);
//将多段线网格边界的Id加入当前选择集
int lenSubgraphIdArray = subgraphIdArray.length();
subgraphIdArray.append(pPolyline->objectId());
pPolyline->close();
//使用wblock将当前图形数据库中的多段线网格边界及其选择集导出到一个新的图形数据库中
Acad::ErrorStatus es = pSourceDb->wblock(pSubgraphDestDb, subgraphIdArray, AcGePoint3d::kOrigin);
assert (es == Acad::eOk);
//调用GenerateSubgraphFileName生成子图的文件名
CString subgraphFileName;
GenerateSubgraphFileName(subgraphIdArray, _T("网格编号"), subgraphFileName);
//将切分出来的子图存为dwg文件
if ("" == subgraphFileName)
{
CString d;
d.Format(_T("%d"),i);//整型转字符串
pSubgraphDestDb->saveAs(_T("E:/PartialGraph/" + d + ".dwg")); // 使用saveAs成员函数时,必须指定包含dwg扩展名的文件名称
}
else
{
pSubgraphDestDb->saveAs(_T("E:/PartialGraph/" + subgraphFileName + ".dwg")); // 使用saveAs成员函数时,必须指定包含dwg扩展名的文件名称
}
pSubgraphDestDb->closeInput(true);
delete pSubgraphDestDb;
pSubgraphDestDb = NULL;
}
}
pSourceDb = NULL;
}
} ;
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CSegmentationByGridApp)
ACED_ARXCOMMAND_ENTRY_AUTO(CSegmentationByGridApp, GYDLSegmentationByGrid, dividedByGrid, dividedByGrid, ACRX_CMD_TRANSPARENT | ACRX_CMD_NOINTERNALLOCK, NULL) |
|