admin 发表于 2024-3-14 20:11:44

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

/*
本程序的步骤及方法 备忘录:
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.isEqualTo(pts)==Adesk::kTrue)
      {
       pts.removeLast();
      }
    //为斜线两点时,作为矩形选择框。但水平或垂直时除外
    if (pts.length() == 2)
    {
                if((fabs(pts.x-pts.x)<0.0001)||(fabs(pts.y-pts.y)<0.0001))
                {
                  acutPrintf("\n边界不能仅为单个水平或垂直线!");
                        return;
                }
                else
                {
                        AcGePoint2d p1(pts.x, pts.y);
                        AcGePoint2d p3(pts.x, pts.y);
                        pts.insertAt(1, p1);
                        pts.insertAt(3, p3);
                }
      }
    //多边形不能少于3点
      if(pts.length() < 3)
      {
                acutPrintf("\n边界点数太少!");
                return;
      }
      //最后线设置为平行或垂直
      if(fabs(pts-pts)<fabs(pts-pts))
      {
       pts=pts;
      }
    else
      {
       pts=pts;
      }
      //闭合起点与终点,画临时直线
    acedGrDraw(asDblArray(pts),asDblArray(pts),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),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);
      }
      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.x,pts.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裁剪,生成局部放大图,成功!");
}
页: [1]
查看完整版本: [每日一码] 裁剪命令xclip只能用于块插入,外部块参考;换种方法,可以实现对所有实体集的裁剪