找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1685|回复: 4

[分享] 实体集的最小矩形框。在钣金展开异形件,备料时,也许多得上

[复制链接]

已领礼包: 271个

财富等级: 日进斗金

发表于 2016-12-15 15:19:29 | 显示全部楼层 |阅读模式

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

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

×
  1. /*在网上看到:Lee Mac LISP_Programming写的相关LISP程序,较好,学习其算法思路。
  2. 但在多次均匀旋转角度在[0,180]范围内查询最小面积时,也许会正好错过实体上的轮廓特殊点线,导致计算结果总与实际轮廓线,总差那么一丁点。
  3. 我的程序,加进了对轮廓线上的特殊点角度的计算处理,解决了上述问题!!!
  4. */
  5. void draw_Min_EntSet_Box()
  6. {
  7.     AcDbObjectIdArray objIdArr;
  8.     ads_name ss={0L,0L};
  9.   //选择实体
  10.   if(acedSSGet(NULL,NULL,NULL,NULL,ss)!=RTNORM)
  11.   {
  12.     acutPrintf("\n用户取消!");
  13.     return;
  14.   }
  15.     long len=0;
  16.   acedSSLength(ss,&len);
  17.   for(int i=0;i<len;i++)
  18.   {
  19.     ads_name ent={0L,0L};
  20.     acedSSName(ss,i,ent);
  21.     AcDbObjectId objId;
  22.     acdbGetObjectId(objId,ent);
  23.         objIdArr.append(objId);
  24.   }
  25.   acedSSFree(ss);
  26.    //获得实体组端点线组成的特殊角度:从小到大
  27.     CArray<double,double> angArr;
  28.     getEntsPtAngle(objIdArr,angArr);
  29.   //
  30.     //初始状态:获得实体组的范围
  31.   AcDbExtents ext0;
  32.     Get_AllEnt_Extents(objIdArr,ext0);
  33.     AcGePoint3d centerPt=ext0.minPoint()+(ext0.maxPoint()-ext0.minPoint())/2.0;
  34.   //最小值
  35.   double minAngle=0.0;
  36.     AcDbExtents minExt=ext0;
  37.     //
  38.     int n=2000;
  39.     //acutPrintf("\n进入角度循环!");
  40.   for(int j=1;j<n;j++)
  41.   {
  42.        double curAngle=j*PI/n;
  43.      //acutPrintf("\n当前旋转角:%f",curAngle);
  44.        AcDbExtents curExt;
  45.        rotateEntSet(objIdArr,centerPt,curAngle);
  46.        Get_AllEnt_Extents(objIdArr,curExt);
  47.        rotateEntSet(objIdArr,centerPt,-curAngle);
  48.      double curArea,minArea;
  49.        curArea=(curExt.maxPoint()[0]-curExt.minPoint()[0])*(curExt.maxPoint()[1]-curExt.minPoint()[1]);
  50.        minArea=(minExt.maxPoint()[0]-minExt.minPoint()[0])*(minExt.maxPoint()[1]-minExt.minPoint()[1]);
  51.      //acutPrintf("\n当前面积:%f;最小面积:%f",curArea,minArea);
  52.      if(curArea<minArea)
  53.      {
  54.           minExt.set(curExt.minPoint(),curExt.maxPoint());;
  55.           minAngle=curAngle;
  56.      }
  57.        //
  58.      if(j==n-1)
  59.      {
  60.        acutPrintf("\n暴力浏览:%d 次完毕!",n);
  61.      }
  62.   }
  63.     //
  64.   //acutPrintf("\n特殊点的角度数:%d",angArr.GetSize());
  65.     //特殊角度
  66.   for(int k=0;k<angArr.GetSize();k++)
  67.   {
  68.        double curAngle=angArr[k];
  69.        AcDbExtents curExt;
  70.        rotateEntSet(objIdArr,centerPt,-curAngle);
  71.        Get_AllEnt_Extents(objIdArr,curExt);
  72.        rotateEntSet(objIdArr,centerPt,curAngle);
  73.      double curArea,minArea;
  74.        curArea=(curExt.maxPoint()[0]-curExt.minPoint()[0])*(curExt.maxPoint()[1]-curExt.minPoint()[1]);
  75.        minArea=(minExt.maxPoint()[0]-minExt.minPoint()[0])*(minExt.maxPoint()[1]-minExt.minPoint()[1]);
  76.      //acutPrintf("\n当前面积:%f;最小面积:%f",curArea,minArea);
  77.      if(curArea-minArea<0.0)
  78.      {
  79.           minExt.set(curExt.minPoint(),curExt.maxPoint());;
  80.           minAngle=-curAngle;
  81.       acutPrintf("\n特殊点角度的最小值交换:成功!");
  82.      }
  83.      else
  84.      {
  85.       ;//acutPrintf("\n特殊点的最小值:不交换!");
  86.      }

  87.      if(k==angArr.GetSize()-1)
  88.      {
  89.        acutPrintf("\n特殊点角度浏览:%d 次完毕!",angArr.GetSize());
  90.      }
  91.   }
  92.     //特殊角度
  93.     //
  94.   //建立矩形
  95.     //AcDbExtents minExt;
  96.     AcDbPolyline* pPLine=new AcDbPolyline();
  97.     pPLine->addVertexAt(0,AcGePoint2d(minExt.minPoint()[0],minExt.minPoint()[1]));
  98.     pPLine->addVertexAt(1,AcGePoint2d(minExt.maxPoint()[0],minExt.minPoint()[1]));
  99.     pPLine->addVertexAt(2,AcGePoint2d(minExt.maxPoint()[0],minExt.maxPoint()[1]));
  100.     pPLine->addVertexAt(3,AcGePoint2d(minExt.minPoint()[0],minExt.maxPoint()[1]));
  101.   pPLine->setClosed(Adesk::kTrue);
  102.     //加入
  103.   AcDbBlockTable* pBT=NULL;
  104.   AcDbBlockTableRecord* pBTRec=NULL;
  105.   acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBT,AcDb::kForRead);
  106.   pBT->getAt(ACDB_MODEL_SPACE,pBTRec,AcDb::kForWrite);
  107.   pBT->close();
  108.   pBTRec->appendAcDbEntity(pPLine);
  109.   //转换
  110.   //acutPrintf("\n旋转角:%f",minAngle*180/PI);
  111.     AcGeMatrix3d xform;
  112.   xform.setToRotation(-minAngle,AcGeVector3d(0,0,1),centerPt);
  113.     pPLine->transformBy(xform);
  114.   //
  115.   pPLine->close();
  116.   pBTRec->close();
  117.     //
  118. }


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

已领礼包: 271个

财富等级: 日进斗金

 楼主| 发表于 2016-12-15 15:35:57 | 显示全部楼层
  1. //实体组的旋转变换
  2. bool rotateEntSet(AcDbObjectIdArray& objIdArr,AcGePoint3d centerPt,double angle)
  3. {
  4.   for(int i=0;i<objIdArr.logicalLength();i++)
  5.   {
  6.         AcGeMatrix3d xform;
  7.     xform.setToRotation(angle,AcGeVector3d(0,0,1),centerPt);
  8.     AcDbEntity* pEnt=NULL;
  9.     acdbOpenAcDbEntity(pEnt,objIdArr,AcDb::kForWrite);
  10.     pEnt->transformBy(xform);
  11.     pEnt->close();
  12.   }
  13.   //
  14.   return true;
  15. }

  16. // 20 获得块引用实体的范围
  17. Acad::ErrorStatus Get_Ent_Extent(const AcDbObjectId& idEnt, AcDbExtents& extents)
  18. {
  19.   Acad::ErrorStatus es;
  20.   AcDbEntity *pEnt = NULL;
  21.   if (Acad::eOk == acdbOpenObject(pEnt, idEnt, AcDb::kForRead))
  22.   {
  23.     if(pEnt->isKindOf(AcDbBlockReference::desc()))
  24.     {
  25.    
  26.         AcDbBlockReference *pBlkRef = AcDbBlockReference::cast(pEnt);
  27.             es = pBlkRef->geomExtentsBestFit(extents);
  28.     }

  29.     else
  30.     {
  31.       es = pEnt->getGeomExtents(extents);
  32.     }
  33.     pEnt->close();
  34.   }
  35.   
  36.   return (es);
  37. }

  38. // 21 获得实体组的范围
  39. void Get_AllEnt_Extents(const AcDbObjectIdArray& aridEnt, AcDbExtents& extents)
  40. {
  41.   for (int i = 0; i<aridEnt.length();i++)
  42.   {
  43.     AcDbExtents tem;
  44.     if (Get_Ent_Extent(aridEnt, tem) == Acad::eOk)
  45.     {
  46.       extents.addExt(tem);//最大框
  47.     }
  48.   }
  49. }
  50. //获得实体组端点线组成的特殊角度:从小到大
  51. bool getEntsPtAngle(AcDbObjectIdArray objIdArr,CArray<double,double>& angArr)
  52. {
  53.   //点集--------------------------------------------------------
  54.   CArray<AcGePoint3d,AcGePoint3d> ptArr;
  55.   for(int i=0;i<objIdArr.logicalLength();i++)
  56.   {
  57.        AcDbEntity* pEnt=NULL;
  58.      acdbOpenAcDbEntity(pEnt,objIdArr,AcDb::kForRead);

  59.      //1 AcDbLine
  60.      if(pEnt->isKindOf(AcDbLine::desc()))
  61.      {
  62.        AcDbLine* pLine=AcDbLine::cast(pEnt);
  63.        AcGePoint3d pt1,pt2;
  64.        pt1=pLine->startPoint();
  65.        pt2=pLine->endPoint();

  66.        //数组中还没有点时
  67.            if(ptArr.GetSize()<1)
  68.        {
  69.          if(pt1.distanceTo(pt2)<0.01)
  70.          {
  71.                   ptArr.Add(pt1);
  72.          }
  73.          else
  74.          {
  75.                   ptArr.Add(pt1);
  76.                   ptArr.Add(pt2);
  77.          }
  78.        }
  79.        else
  80.        {
  81.          //pt1
  82.          for(int h=0;h<ptArr.GetSize();h++)
  83.          {
  84.                if(pt1.distanceTo(ptArr[h])<0.01)
  85.            {
  86.              break;
  87.            }

  88.            if(h==ptArr.GetSize()-1)
  89.            {
  90.                        ptArr.Add(pt1);
  91.            }
  92.          }
  93.          //pt2
  94.          if(pt1.distanceTo(pt2)>0.01)
  95.          {
  96.            for(int j=0;j<ptArr.GetSize();j++)
  97.            {
  98.              if(pt2.distanceTo(ptArr[j])<0.01)
  99.              {
  100.                break;
  101.              }
  102.             
  103.              if(j==ptArr.GetSize()-1)
  104.              {
  105.                ptArr.Add(pt2);
  106.              }
  107.            }
  108.          }
  109.          else
  110.          {
  111.            ;
  112.          }
  113.        }
  114.      }
  115.      //1 AcDbLine

  116.        //2 AcDbArc
  117.        else if(pEnt->isKindOf(AcDbArc::desc()))
  118.      {
  119.        AcDbArc* pArc=AcDbArc::cast(pEnt);
  120.        AcGePoint3d pt1,pt2;
  121.        pt1=pArc->center()+pArc->radius()*AcGeVector3d(cos( pArc->startAngle()),sin( pArc->startAngle()),0);  
  122.        pt2=pArc->center()+pArc->radius()*AcGeVector3d(cos( pArc->endAngle()),sin( pArc->endAngle()),0);
  123.   
  124.           //数组中还没有点时
  125.            if(ptArr.GetSize()<1)
  126.        {
  127.          if(pt1.distanceTo(pt2)<0.01)
  128.          {
  129.                   ptArr.Add(pt1);
  130.          }
  131.          else
  132.          {
  133.                   ptArr.Add(pt1);
  134.                   ptArr.Add(pt2);
  135.          }
  136.        }
  137.        else
  138.        {
  139.          //pt1
  140.          for(int h=0;h<ptArr.GetSize();h++)
  141.          {
  142.                if(pt1.distanceTo(ptArr[h])<0.01)
  143.            {
  144.              break;
  145.            }

  146.            if(h==ptArr.GetSize()-1)
  147.            {
  148.                        ptArr.Add(pt1);
  149.            }
  150.          }
  151.          //pt2
  152.          if(pt1.distanceTo(pt2)>0.01)
  153.          {
  154.            for(int j=0;j<ptArr.GetSize();j++)
  155.            {
  156.              if(pt2.distanceTo(ptArr[j])<0.01)
  157.              {
  158.                break;
  159.              }
  160.             
  161.              if(j==ptArr.GetSize()-1)
  162.              {
  163.                ptArr.Add(pt2);
  164.              }
  165.            }
  166.          }
  167.          else
  168.          {
  169.            ;
  170.          }
  171.        }
  172.      }
  173.      //2 AcDbArc

  174.        //3 AcDbPolyline
  175.        else if(pEnt->isKindOf(AcDbPolyline::desc()))
  176.      {
  177.        AcDbPolyline* pPLine=AcDbPolyline::cast(pEnt);
  178.        AcGePoint3d pt;
  179.            for(int i=0;i<pPLine->numVerts();i++)
  180.        {
  181.         pPLine->getPointAt(i,pt);
  182.         if(ptArr.GetSize()<1)
  183.         {
  184.              ptArr.Add(pt);
  185.         }
  186.         else
  187.         {
  188.           //
  189.                    for(int j=0;j<ptArr.GetSize();j++)
  190.            {
  191.              if(pt.distanceTo(ptArr[j])<0.01)
  192.              {
  193.                break;
  194.              }
  195.             
  196.              if(j==ptArr.GetSize()-1)
  197.              {
  198.                ptArr.Add(pt);
  199.              }
  200.            }
  201.           //
  202.         }
  203.        }
  204.            
  205.   
  206.      }
  207.      //3 AcDbPolyline
  208.      //
  209.      pEnt->close();
  210.   }
  211.     //acutPrintf("\n共需计算:%d个点!",ptArr.GetSize());
  212.   //点集--------------------------------------------------------
  213.   if(ptArr.GetSize()<2)
  214.   {
  215.     acutPrintf("\n点数太少!");
  216.     return false;
  217.   }
  218.     //
  219.     //暴力求角度集
  220.   for(i=0;i<ptArr.GetSize()-1;i++)
  221.   {
  222.         for(int j=i+1;j<ptArr.GetSize();j++)
  223.     {
  224.             double dAngle;
  225.       //始向量:+x轴,右手旋转
  226.             dAngle=AcGeVector3d(100,0,0).angleTo(AcGeVector3d(ptArr-ptArr[j]),AcGeVector3d(0,0,1));//[0,360]
  227.             angArr.Add(dAngle);
  228.             //acutPrintf("\n角度:%f",dAngle);
  229.     }
  230.    
  231.   }
  232.   
  233.   //
  234.   return true;
  235. }

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

使用道具 举报

已领礼包: 271个

财富等级: 日进斗金

 楼主| 发表于 2016-12-15 15:39:31 | 显示全部楼层
代码不太简捷,漂亮,也没有优化,请朋友们多多指教!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 13个

财富等级: 恭喜发财

发表于 2016-12-15 20:44:10 | 显示全部楼层
很好的代码,旋转那个里面

acdbOpenAcDbEntity(pEnt,objIdArr<i>,AcDb::kForWrite);
    pEnt->transformBy(xform);

建议判断下返回值,避免异常情况,其他地方也是如此,尽量都判断返回值再下一步处理。
AcadErrorStatus es = acdbOpenAcDbEntity(pEnt,objIdArr<i>,AcDb::kForWrite);
if (es == Acad::eOk || es == Acad::eWasOpenForWrite)
   pEnt->transformBy(xform);
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-15 05:27 , Processed in 0.385968 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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