找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1593|回复: 4

[每日一码] 裁剪命令xclip只能用于块插入,外部块参考;换种方法,可以实现对所有实体集的裁剪

[复制链接]

已领礼包: 271个

财富等级: 日进斗金

发表于 2016-12-14 10:30:33 | 显示全部楼层 |阅读模式

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

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

×
/*
本程序的步骤及方法 备忘录:
  1 多边形选择实体("CP")
  2 建立匿名块,将以上选择集,克隆到匿名块中
  3 在与块定义重合的位置,插入块引用
  4 以多边形的点集,组成裁剪平面,给块引用加与裁剪相关的扩展词典,
    实现与命令xclip相同的对块引用的裁剪
  5 沿裁剪边界,绘制边界多义线,以便可以对边界修改为双点划线等
  6 点取放大图移出点及放大倍数,将以上裁剪后的块引用及边界多义线,进行平移,放大变换。
    这样,就完成了局部放大图的操作。
  注:xclip仅对块引用及外部参考进行裁剪操作。本程序克服了这一限制,可以对任何实体集进行裁剪操作
*/
//代替命令:xclip,生成局部放大图
void all_clip()
{
        acutPrintf("\n----裁剪,生成局部放大图:");
        //1 设置xclip不画边界线
        acedCommand(RTSTR,"setvar",
                RTSTR,"xclipframe",
                RTSTR,"0",
                0);
        //正交,让点取线为水平或垂直
        acedCommand(RTSTR,"setvar",
                RTSTR,"orthomode",
                RTSTR,"1",
                0);

        //2 取边界点
    //pt0:块的定义点,及引用的插入点
    ads_point pt0;
        ads_point pt1,pt2;
    AcGePoint2dArray pts;
        acutPrintf("\n点选区域点:");
    if (acedGetPoint(NULL,_T("\n第1点:"),pt1)!=RTNORM)
        {
                acutPrintf("\n用户取消!");
            //取消正交
            acedCommand(RTSTR,"setvar",
                RTSTR,"orthomode",
                RTSTR,"0",
                0);
        //
        return;
        }
        ads_point_set(pt1,pt0);//pt0=pt1
    pts.append(asPnt2d(pt1));
        int es0;
    while ((es0=acedGetPoint(pt1,_T("\n下一点<回车,结束取点>:"),pt2))==RTNORM)
    {
                //画临时线,作为标志
        acedGrDraw(pt1,pt2,1,1);
        pts.append(asPnt2d(pt2));
        ads_point_set(pt2,pt1);//pt1=pt2
    }
        if(es0==RTCAN)
        {
                acutPrintf("\n用户取消!");
                //取消正交
                acedCommand(RTSTR,"setvar",
                        RTSTR,"orthomode",
                        RTSTR,"0",
                        0);
                return;
        }
        //取消正交
        acedCommand(RTSTR,"setvar",
                RTSTR,"orthomode",
                RTSTR,"0",
                0);
    //起点与终点重合时,仅记作起点
        if(pts[0].isEqualTo(pts[pts.logicalLength()-1])==Adesk::kTrue)
        {
       pts.removeLast();
        }
    //为斜线两点时,作为矩形选择框。但水平或垂直时除外
    if (pts.length() == 2)
    {
                if((fabs(pts[0].x-pts[1].x)<0.0001)||(fabs(pts[0].y-pts[1].y)<0.0001))
                {
                    acutPrintf("\n边界不能仅为单个水平或垂直线!");
                        return;
                }
                else
                {
                        AcGePoint2d p1(pts[1].x, pts[0].y);
                        AcGePoint2d p3(pts[0].x, pts[1].y);
                        pts.insertAt(1, p1);
                        pts.insertAt(3, p3);
                }
        }
    //多边形不能少于3点
        if(pts.length() < 3)
        {
                acutPrintf("\n边界点数太少!");
                return;
        }
        //最后线设置为平行或垂直
        if(fabs(pts[0][0]-pts[pts.logicalLength()-1][0])<fabs(pts[0][0]-pts[pts.logicalLength()-1][0]))
        {
       pts[pts.logicalLength()-1][0]=pts[0][0];
        }
    else
        {
       pts[pts.logicalLength()-1][1]=pts[0][1];
        }
        //闭合起点与终点,画临时直线
    acedGrDraw(asDblArray(pts[0]),asDblArray(pts[pts.logicalLength()-1]),1,1);

        //3 多边形交叉选择实体:CP
        //3.1 建立多边形点链表
        ads_name ss={0L,0L};
    struct resbuf *pointList=NULL;
    struct resbuf *nextNode=NULL;
    for(int i=0;i<pts.logicalLength();i++)
        {
                //点表
        struct resbuf *newNode=acutNewRb(RTPOINT);
        ads_point_set(asDblArray(pts[i]),newNode->resval.rpoint);//(from,to)
                if(pointList==NULL)
                {
           pointList=newNode;
           nextNode=newNode;
                }
                else
                {
           nextNode->rbnext=newNode;
           nextNode=newNode;
                }  
        }
        //3.2 多边形选择:"CP"
        if(acedSSGet("CP",pointList,NULL,NULL,ss)!=RTNORM)
        {
                acutRelRb(pointList);
                acutPrintf("\n错误退出!");
                return;
        }
    acutRelRb(pointList);

        //4 输入插入点,放大倍数
        AcGePoint3d insPt;
    if (acedGetPoint(pt1,_T("\n输入放大图的插入点:"),asDblArray(insPt))!=RTNORM)
        {
                acutPrintf("\n用户取消!");
                acedSSFree(ss);
        return;
        }
        double scl=1;
        acedInitGet(RSG_NOZERO+RSG_NONEG,NULL);//非0,非负
    if ((es0=acedGetReal(_T("\n输入放大倍数<1>:"),&scl))!=RTNORM)
        {
                if(es0==RTNONE)
                {
                        scl=1.0;
                }
                else
                {
                   acutPrintf("\n用户取消!");
                   acedSSFree(ss);
           return;
                }
        }
    acedRedraw(NULL,0);

        //5 并生成匿名块定义,并将选择的实体,拷贝到匿名块定义中
        //5.1 生成匿名块定义
        AcDbBlockTable* pBT=NULL;
    acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBT,AcDb::kForWrite);
        AcDbBlockTableRecord* pBTRec=new AcDbBlockTableRecord();
        AcDbObjectId myBTRecId;
    pBT->add(myBTRecId,pBTRec);
        pBT->close();
        pBTRec->setOrigin(asPnt3d(pt0));
    pBTRec->setName("*U");//匿名
    //5.2 将选择的实体,克隆到块定义中
    long nLen;
        acedSSLength(ss,&nLen);
        AcDbObjectIdArray m_objId_arr;
        for(i=0;i<nLen;i++)
        {
                ads_name ent;
                acedSSName(ss,i,ent);
                AcDbObjectId objId;
                acdbGetObjectId(objId,ent);
        m_objId_arr.append(objId);

        }
        acedSSFree(ss);
    pBTRec->close();
        AcDbIdMapping idMap;
    if(acdbHostApplicationServices()->workingDatabase()->deepCloneObjects(m_objId_arr,myBTRecId,idMap)!=Acad::eOk)
        {
                acutPrintf("\n将选择的实体克隆到块定义中,失败!");
                return;
        }

        //6 在选择的实体相同处,插入块引用
        //6.1  设置插入点,旋转角度,比例等等  
        AcDbBlockReference *pMyRef =new AcDbBlockReference() ;  
        pMyRef->setBlockTableRecord (myBTRecId) ;  
        pMyRef->setScaleFactors(AcGeScale3d(1,1,1));
        pMyRef->setPosition(asPnt3d(pt0)) ;  
        pMyRef->setRotation (0.0) ;  
        //6.2 将块引用,加入模型空间块表记录  
        AcDbBlockTable *pBlockTable=NULL ;  
        acdbHostApplicationServices()->workingDatabase()->getBlockTable (pBlockTable, AcDb::kForRead) ;  
        AcDbBlockTableRecord *pBlockTableRecord ;  
        pBlockTable->getAt (ACDB_MODEL_SPACE, pBlockTableRecord,AcDb::kForWrite) ;  
        pBlockTable->close () ;  
        AcDbObjectId myRefId;
        pBlockTableRecord->appendAcDbEntity(myRefId,pMyRef);
    pMyRef->close();

        //7 用以上的选择框,建立多义线,作为外框线,并进行与块引用相同的移动,放大变换
        AcDbPolyline* pPLine=new AcDbPolyline();
    for(i=0;i<pts.logicalLength();i++)
        {
       pPLine->addVertexAt(i,pts[i]);
        }
        pPLine->setClosed(Adesk::kTrue);
    AcGeMatrix3d matPLine;
        matPLine.setTranslation(insPt-asPnt3d(pt0));//平移
    pPLine->transformBy(matPLine);
    matPLine.setToScaling(scl,insPt);//放大
    pPLine->transformBy(matPLine);
        AcDbObjectId plineId;
        pBlockTableRecord->appendAcDbEntity(plineId,pPLine);
    pPLine->close();
        pBlockTableRecord->close();

        //8 对以上块引用,加裁剪处理(与xclip命令相同的功能)
    AcDbObjectPointer<AcDbBlockReference> pRef(myRefId,AcDb::kForRead);
    if (pRef.openStatus()!=Acad::eOk)
    {
        acutPrintf(_T("Not an xref!\n"));
        return;
    }
    //从WCS转换为ECS
    AcGeMatrix3d mat(pMyRef->blockTransform());
    mat.invert();
    AcGePoint2dArray ecsPts;
        for(i=0;i<pts.logicalLength();i++)
        {
                AcGePoint3d pt(AcGePoint3d(pts[i].x,pts[i].y,0));
        //pt.transformBy(mat);
        ecsPts.append(AcGePoint2d(pt.x,pt.y));
        }
        //求其它参数
    AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
    AcGeVector3d normal;
    double elev;
    if (pDb->tilemode())//=1,模型空间
    {
        normal = pDb->ucsxdir().crossProduct(pDb->ucsydir());
        elev = pDb->elevation();
    }
    else //=0,图纸空间
    {
        normal = pDb->pucsxdir().crossProduct(pDb->pucsydir());
        elev = pDb->pelevation();
    }
    normal.normalize();
        //升级打开方式:写
    Acad::ErrorStatus es = pRef.object()->upgradeOpen();
    if (es !=Acad::eOk)
        {
                acutPrintf("\n写打开失败!");
        return;
        }
    //建立过滤对象
    AcDbSpatialFilter* pFilter = new AcDbSpatialFilter;
        //设置
        /*
    if (pFilter->setDefinition(ecsPts,normal,elev,
        ACDB_INFINITE_XCLIP_DEPTH,-ACDB_INFINITE_XCLIP_DEPTH,true)!=Acad::eOk)
    {
        delete pFilter;
        return;
    }
        */
    if (pFilter->setDefinition( ecsPts,AcGeVector3d(0,0,1),0.0,
        ACDB_INFINITE_XCLIP_DEPTH,
        -ACDB_INFINITE_XCLIP_DEPTH,true)!=Acad::eOk)
   {
        delete pFilter;
                acutPrintf("\n退出!");
        return;
    }
    // 加扩展管理
    //add it to the extension dictionary of the block reference
    //the AcDbIndexFilterManger class provides convenient utility functions
    if (AcDbIndexFilterManager::addFilter(pRef.object(),pFilter)!=Acad::eOk)
        {
        delete pFilter;
                acutPrintf("\n退出!");

                return;
        }
    else
    {
        acutPrintf(_T("Filter has been succesfully added!\n"));
        pFilter->close();
    }

        //9 裁剪块引用,从原点平移,放大转换
    pRef->setScaleFactors(AcGeScale3d(scl,scl,scl));
        pRef->setPosition(insPt) ;         
    acutPrintf("\n裁剪,生成局部放大图,成功!");
}

评分

参与人数 2威望 +3 D豆 +10 贡献 +4 收起 理由
SmallBlackCat + 3 + 5 + 3 很给力!经验;技术要点;资料分享奖!
newer + 5 + 1 很给力!经验;技术要点;资料分享奖!

查看全部评分

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

已领礼包: 40个

财富等级: 招财进宝

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

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2016-12-14 10:57:38 | 显示全部楼层
楼主,XCLIP对块操作后,随时可以取消,恢复原来的显示,不知道楼主的程序对非图块操作后,如果想恢复能做到吗?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 271个

财富等级: 日进斗金

 楼主| 发表于 2016-12-14 11:21:57 | 显示全部楼层
我只是将要截取的部分,深层克隆到一个匿名块中,再用xclip裁剪这一匿名块引用,与原位置的实体无关。
炸开这个匿名块引用,就是原来选择的实体了
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 2470个

财富等级: 金玉满堂

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-15 05:34 , Processed in 0.292854 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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