找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3989|回复: 4

[求助] 在ObjectARX中,通过CP选择模式在多段线里面选择集另存为dwg文件后,选择集里面是空的

[复制链接]
发表于 2019-4-16 10:34:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
现在遇到的主要问题是,在多段线里面选择集另存为dwg文件后,选择集里面是空的。我现在把代码贴上去了,麻烦诸位仁兄看一下吧,谢谢!接着我把原dwg文件传一下。

//-----------------------------------------------------------------------------
//----- acrxEntryPoint.h
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include <dbpl.h>
#include <gecomp2d.h>
#include "Common\Document\DwgDatabaseUtil.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);
}
//AcDbEntity *pNewPpline = AcDbEntity::cast(pPline->clone());
//ObjectIdArray.append(pNewPpline->objectId());   // 将作为边界的多段线本身的Id也加入到所选择实体的数组中
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;*/

// 使用acedSSGet函数创建选择集
ads_name ssName;   // 选择集名称
int rt = acedSSGet(char2wchar(selectMode), rb, NULL, NULL, ssName);
//int rt = acedSSGet(char2wchar(selectMode), rb, NULL, &rbFilter, ssName);
if (rt != RTNORM)
{
  acutRelRb(rb);   // 释放结果缓冲区链表
  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;
}
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("0"));
  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加入当前选择集
    subgraphIdArray.append(pPolyline->objectId());
    pPolyline->close();
    //使用wblock将当前图形数据库中的多段线网格边界及其选择集导出到一个新的图形数据库中
    Acad::ErrorStatus es = pSourceDb->wblock(pSubgraphDestDb, subgraphIdArray, AcGePoint3d::kOrigin);
    assert (es == Acad::eOk);
    //将切分出来的子图存为dwg文件
    CString d;
    d.Format(_T("%d"),i);//整型转字符串
    pSubgraphDestDb->saveAs(_T("E:/PartialGraph/" + d + ".dwg")); // 使用saveAs成员函数时,必须指定包含dwg扩展名的文件名称
    pSubgraphDestDb->closeInput(true);
    delete pSubgraphDestDb;
    pSubgraphDestDb = NULL;
    subgraphIdArray.removeAll();
    //pPolyline->close();
   }
  }
  pSourceDb = NULL;
}
} ;
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
 楼主| 发表于 2019-4-16 10:38:51 | 显示全部楼层
要处理的CAD图在附件中,谢谢!

电网规划.rar

89.85 KB, 下载次数: 2, 下载积分: D豆 -1 , 活跃度 1

这是要处理的AutoCAD图

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 960个

财富等级: 财运亨通

发表于 2019-4-16 10:42:10 | 显示全部楼层
谢谢楼主分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2019-4-16 13:02:42 | 显示全部楼层
你还要确保选择的实体在屏幕内显示
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-16 13:47:49 | 显示全部楼层
选择的实体在屏幕内显示,这个是没问题的。我刚才使用A模式选择,全部能选择并可以显示。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-4-27 10:58 , Processed in 0.275836 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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