找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3304|回复: 7

[求助] 将选择集复制后缩放并移动到指定位置,复制过程很慢且缩放移动不成功,求原因

[复制链接]

已领礼包: 112个

财富等级: 日进斗金

发表于 2016-5-21 16:21:21 | 显示全部楼层 |阅读模式

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

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

×

目的:选择实体,自动求出选择集的包围盒,用户选择一个范围框,以包围盒与范围框的X、Y两个方向的缩放值的最小值(选择的对象缩放后在范围框中最大且不超出范围框),并使选择集图元的中心位于范围框的中心。现在的问题是对选择集进行复制的过程很慢,100多个图元时感到慢了,而且缩放与移动不执行。缩放和移动函数来自张帆的书。
       static void YTMsupportWZZZ(void)        {
                ////遍历所有实体  
                Acad::ErrorStatus es;
                ads_name sset;////选择集名称
                AcDbObjectIdArray entIds;
                entIds.setLogicalLength(0);
                //建议缓冲区链表
                struct resbuf *rb;//结果缓冲表
                //rb=acutBuildList(RTDXF0,TEXT("DIMENSION"),RTNONE);
                rb=acutBuildList(-4,TEXT("<OR"),RTDXF0,TEXT("DIMENSION"),RTDXF0,TEXT("TOLERANCE"),RTDXF0,TEXT("INSERT"),-4,TEXT("OR>"),RTNONE);
                //if(acedSSGet(_T("X"),NULL,NULL,rb,sset)==RTNORM)
                if(acedSSGet(NULL,NULL,NULL,NULL,sset)==RTNORM)
                {
                        long length=0;
                        acedSSLength(sset,&length);
                        acutPrintf(TEXT("\n实体数:%d"),length);
                        for(int i=0;i<length;i++)
                        {
                                ads_name ename;
                               
                                acedSSName(sset,i,ename);
                                AcDbObjectId entId;
                                //获取图元ID
                                es=acdbGetObjectId(entId,ename);
                                if(es == Acad::eOk)
                                {
                                        entIds.append(entId);                                       
                                }
                               
                        }
                        AcDbExtents extents;
                        extents=CCreatEnt::GetGeomExtents(entIds);
                        AcGePoint3d ssMidpt;
                        AcGePoint3d pt1=extents.minPoint();
                        AcGePoint3d pt2=extents.maxPoint();
                        ssMidpt=AcGePoint3d((pt2.x + pt1.x) / 2.0, (pt2.y + pt1.y) / 2.0, 0.0);
                        double lx=pt2.x - pt1.x;
                        double ly=pt2.y - pt1.y;

                        ads_point gopt1;
                        ads_point gopt2;
                        AcGePoint3d goMidpt;
                        if(acedGetPoint(NULL, _T("\n请选择左上角点:"), gopt1)==RTNORM)
                        {
                                if(acedGetCorner(gopt1, _T("\n请选择右下角点:"), gopt2)==RTNORM)
                                {
                                        goMidpt.x=(gopt1[X]+gopt2[X])*0.5;
                                        goMidpt.y=(gopt1[Y]+gopt2[Y])*0.5;
                                        goMidpt.z=(gopt1[Z]+gopt2[Z])*0.5;
                                        double xsc=abs((gopt1[X]-gopt2[X])/lx);
                                        double ysc=abs((gopt1[Y]-gopt2[Y])/ly);
                                        double sc=min(xsc,ysc);
                                        for(int i=0;i<entIds.length();i++)
                                        {
                                                //打开实体
                                                AcDbEntity *pEnt=NULL;
                                                AcDbDimension *pDim=NULL;
                                                AcDbFcf *pFcf=NULL;
                                                //AcDbDimension *pFcf=NULL;
                                                es=acdbOpenObject(pEnt,entIds[i],AcDb::kForRead);
                                                if(es == Acad::eOk)
                                                {
                                                        AcRxObject *pObject = pEnt->clone();
                                                        if (pObject != NULL)
                                                        {
                                                                AcDbEntity *pOtherEnt = AcDbEntity::cast(pObject);
                                                                if (pOtherEnt != NULL)
                                                                {
                                                                        CCreatEnt::PostToModelSpace(pOtherEnt);
                                                                        CCreatEnt::SetColor(entIds[i],1);
                                                                        CCreatEnt::Scale(entIds[i],ssMidpt,10.0);
                                                                        CCreatEnt::Move(entIds[i],ssMidpt,goMidpt);
                                                                }
                                                        }
                                                }
                                                //注意需要关闭实体
                                                if (pEnt!=NULL)
                                                {
                                                        pEnt->close();
                                                }
                                        }
                                        acutPrintf(_T("\n中点X:%f"),goMidpt.x);
                                        acutPrintf(_T("\n中点Y:%f"),goMidpt.y);
                                        acutPrintf(_T("\n中点Z:%f"),goMidpt.z);
                                        acutPrintf(_T("\n缩放X:%f"),xsc);
                                        acutPrintf(_T("\n缩放Y:%f"),ysc);
                                        acutPrintf(_T("\n最小缩放:%f"),sc);
                                        acutPrintf(_T("\n中点X:%f"),ssMidpt[X]);
                                        acutPrintf(_T("\n中点X:%f"),ssMidpt[Y]);
                                        acutPrintf(_T("\n中点X:%f"),ssMidpt[Z]);
                                }
                                else
                                {
                                        for(int i=0;i<entIds.length();i++)
                                        {
                                                CCreatEnt::Erase(entIds[i]);
                                        }
                                }
                        }
                        else
                        {
                                for(int i=0;i<entIds.length();i++)
                                {
                                        CCreatEnt::Erase(entIds[i]);
                                }
                        }
                }
                //关闭链表
                acutRelRb(rb);
                //关闭选择集
                acedSSFree(sset);

        }
Acad::ErrorStatus CCreatEnt::Move( AcDbObjectId entId, const AcGePoint3d &ptBase, const AcGePoint3d &ptDest )
{
        // 设置变换矩阵的参数
        AcGeMatrix3d xform;       
        AcGeVector3d vec(ptDest.x - ptBase.x, ptDest.y - ptBase.y,
                ptDest.z - ptBase.z);
        xform.setToTranslation(vec);

        AcDbEntity *pEnt = NULL;
        Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite, false);
        if (es == Acad::eOk)
        {
                es = pEnt->transformBy(xform);
                pEnt->close();
        }

        return es;
}

Acad::ErrorStatus CCreatEnt::Scale( AcDbObjectId entId, const AcGePoint3d &ptBase, double scaleFactor )
{
        // 设置变换矩阵的参数
        AcGeMatrix3d xform;               
        xform.setToScaling(scaleFactor, ptBase);

        AcDbEntity *pEnt = NULL;
        Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite, false);
        if (es == Acad::eOk)
        {
                es = pEnt->transformBy(xform);
                pEnt->close();
        }

        return es;
}

void CCreatEnt::Erase( AcDbObjectId entId )
{
        AcDbEntity *pEnt = NULL;
        if (acdbOpenObject(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
        {
                pEnt->erase();
                pEnt->close();
        }
}



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

已领礼包: 112个

财富等级: 日进斗金

 楼主| 发表于 2016-5-21 16:26:04 | 显示全部楼层
CCreatEnt::SetColor(entIds[i],1);
CCreatEnt::Scale(entIds[i],ssMidpt,10.0);
CCreatEnt::Move(entIds[i],ssMidpt,goMidpt);
这三句不运行,但也没报错。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2016-5-21 16:36:21 | 显示全部楼层
es=acdbOpenObject(pEnt,entIds[i],AcDb::kForRead); =====》 read?
if(es == Acad::eOk)
{
        AcRxObject *pObject = pEnt->clone();  =======>clone();

点评

C++和arx双重新手,请问正确的应该如何写?  详情 回复 发表于 2016-5-21 17:08
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 112个

财富等级: 日进斗金

 楼主| 发表于 2016-5-21 17:08:51 | 显示全部楼层
st788796 发表于 2016-5-21 16:36
es=acdbOpenObject(pEnt,entIds,AcDb::kForRead); =====》 read?
if(es == Acad::eOk)
{

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

使用道具 举报

已领礼包: 112个

财富等级: 日进斗金

 楼主| 发表于 2016-5-21 17:21:34 | 显示全部楼层
复制
BOOL Copy(AcDbObjectId entId, const AcGePoint3d ptFrom,const AcGePoint3d ptTo)
{
AcDbEntity *pEnt = NULL;* ]% y: G6 _0 {$ g% O' _
if (acdbOpenObject(pEnt, entId , AcDb::kForRead) != Acad::eOk)1 e" l3 P# d0 J/ ]6 @3 H8 ~
return FALSE;
AcDbEntity *pCopyEnt = AcDbEntity::cast(pEnt->clone());
AcDbObjectId copyEntId;6 j. ]' Q# @% N! b6 H) B1 D/ O. `
if (pCopyEnt)* |- K: y, W' V
copyEntId = PostToModelSpace(pCopyEnt);3 h* D! s  J! B1 u
Move(copyEntId, ptFrom, ptTo);
return TRUE;
}
复制部分代码参考http://www.3dportal.cn/discuz/fo ... ead&tid=1431634
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2016-5-21 21:05:07 | 显示全部楼层
本帖最后由 st788796 于 2016-5-21 22:38 编辑
革天明 发表于 2016-5-21 17:21
复制
BOOL Copy(AcDbObjectId entId, const AcGePoint3d ptFrom,const AcGePoint3d ptTo)
{

ARX 不是这样学吧

  1. static void YTMsupportWZZZ(void)        
  2.         {
  3.                 ads_name sset;        
  4.                 struct resbuf *rb=NULL;
  5.                 rb=acutBuildList(RTDXF0,TEXT("DIMENSION,TOLERANCE,INSERT"),RTNONE);
  6.                 int ret=acedSSGet(NULL,NULL,NULL,NULL,sset);
  7.                 acutRelRb(rb);
  8.                 if (ret!=RTNORM)
  9.                         return;
  10.                 long length;
  11.                 acedSSLength(sset,&length);                        
  12.                 acutPrintf(TEXT("\n实体数:%d"),length);
  13.                 ads_point pt1,pt2;
  14.                 ret=acedGetPoint(NULL, _T("\n请选择第一角点:"), pt1);
  15.                 if (ret!=RTNORM)
  16.                         return;
  17.                 ret=acedGetCorner(pt1, _T("\n请选择对角点:"), pt2);
  18.                 if (ret!=RTNORM)
  19.                         return;
  20.                 double vx=fabs(pt2[X]-pt1[X]);
  21.                 double vy=fabs(pt2[Y]-pt1[Y]);
  22.                 if (vx<1e-8||vy<1e-8)
  23.                     return;
  24.                 Acad::ErrorStatus es;
  25.                 AcDbObjectIdArray entIds;
  26.                 AcDbObjectId entId;
  27.                 ads_name ename;
  28.                 AcDbExtents ext,extents;
  29.                 AcDbEntity *pEnt=NULL;
  30.                 for(long i=0;i<length;i++)
  31.                 {                                
  32.                         acedSSName(sset,i,ename);                                
  33.                         es=acdbGetObjectId(entId,ename);                                
  34.                         if(es != Acad::eOk)
  35.                                 continue;   
  36.                         entIds.append(entId);
  37.                         es=acdbOpenObject(pEnt,entId,AcDb::kForRead);
  38.                         if(es != Acad::eOk)
  39.                                 continue;   
  40.                         pEnt->getGeomExtents(extents);
  41.                         pEnt->close();
  42.                         ext.addExt(extents);
  43.                 }
  44.                 acedSSFree(sset);
  45.                 AcGeVector3d vec(ext.maxPoint()-ext.minPoint());
  46.                 AcGePoint3d ptFrom(ext.minPoint()+vec/2);
  47.                 AcGePoint3d ptTo((pt1[X]+pt2[X])/2,(pt1[Y]+pt2[Y])/2,0.0);        
  48.                 double sc=min(vx/vec.x,vy/vec.y);
  49.                 AcGeMatrix3d mat1,mat2,mat;
  50.                 mat1.setTranslation(ptTo-ptFrom);
  51.                 mat2.setToScaling(sc,ptTo);
  52.                 mat.setToProduct(mat2,mat1);
  53.                 AcDbEntity *pNewEnt=NULL;
  54.                 AcDbBlockTableRecordPointer btr(curDoc()->database()->currentSpaceId(),AcDb::kForWrite);
  55.                 if (btr.openStatus()!=Acad::eOk)
  56.                         return;
  57.                 for(int i=0;i<entIds.length();i++)
  58.                 {
  59.                         es=acdbOpenObject(pEnt,entIds.at(i),AcDb::kForWrite);
  60.                         if (es!=Acad::eOk)
  61.                                 continue;
  62.                         es=pEnt->getTransformedCopy(mat,pNewEnt);
  63.                         pEnt->close();
  64.                         if (es==Acad::eOk)
  65.                         {
  66.                                 pNewEnt->setColorIndex(1);
  67.                                 btr->appendAcDbEntity(pNewEnt);
  68.                                 pNewEnt->close();
  69.                         }
  70.                 }
  71.                 acutPrintf(_T("\n中点X:%.3f,Y:%.3f,Z:%.3f"),ptFrom.x,ptFrom.y,ptFrom.z);
  72.                 acutPrintf(_T("\n中点X:%.3f,Y:%.3f,Z:%.3f"),ptTo.x,ptTo.y,ptTo.z);
  73.                 acutPrintf(_T("\n缩放X:%.3f, 缩放Y:%.3f"),vx/vec.x,vy/vec.y);
  74.                 acutPrintf(_T("\n最小缩放:%.3f"),sc);               
  75.         }                        
复制代码
用 XDRXAPI 就是这样

  1. (defun c:tt (/ ss p1 p2        box box1 v1 v2 xc yc sc        pc1 pc2        mat mat0 mat1 mat2)
  2.   (if (and (setq ss (ssget ));'((0 . "DIMENSION,TOLERANCE,INSERT"))))
  3.            (setq p1 (getpoint "\n第一角点: "))
  4.            (setq p2 (getcorner p1 "\n对角点: "))
  5.            (setq box1 (xdrx_points_box (list p1 p2)))
  6.       )
  7.     (progn
  8.       (setq box         (xdrx_entity_box ss)
  9.             pc1         (apply 'xdrx_points_centroid box1)
  10.             pc2         (apply 'xdrx_points_centroid box)
  11.             v1         (mapcar '- (caddr box) (car box))
  12.             v2         (mapcar '- (caddr box1) (car box1))
  13.             xc         (/ (car v2) (car v1))
  14.             yc         (/ (cadr v2) (cadr v1))
  15.             sc         (min xc yc)
  16.             mat0 (xdrx_matrix_identity)
  17.             mat1 (xdrx_matrix_settranslation mat0 (mapcar '- pc1 pc2))
  18.             mat2 (xdrx_matrix_setscale mat0 sc pc1)
  19.             mat         (xdrx_matrix_product mat2 mat1)
  20.       )
  21.       (xdrx_entity_transformedcopy ss mat)
  22.     )
  23.   )
  24.   (princ)
  25. )
慢是因为用的函数太多,变换可以一次到位,不需要 move + copy + scale ...

点评

谢谢指点,完整的代码效率很高,通过阅读代码发现还有很多内容需要学习和理解,谢谢您!  详情 回复 发表于 2016-5-23 11:46
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 13个

财富等级: 恭喜发财

发表于 2016-5-21 22:43:24 | 显示全部楼层
代码太长,说几点意见:

1、POST到数据库时候,会有ID,你就不要在数组中求了,这样能节省时间
2、多次矩阵的变换,不要每次都变换,这样还不慢? 你用矩阵左乘,把最终的变换矩阵求出来,执行一次TRANSFORM就行了。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 112个

财富等级: 日进斗金

 楼主| 发表于 2016-5-23 11:46:23 | 显示全部楼层
st788796 发表于 2016-5-21 21:05
ARX 不是这样学吧用 XDRXAPI 就是这样慢是因为用的函数太多,变换可以一次到位,不需要 move + copy + sc ...

谢谢指点,完整的代码效率很高,通过阅读代码发现还有很多内容需要学习和理解,谢谢您!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-24 16:30 , Processed in 0.216814 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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