找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 8611|回复: 46

[每日一码] (3)获得AcDbSpline准确的包围盒

[复制链接]

已领礼包: 145个

财富等级: 日进斗金

发表于 2014-12-5 20:33:14 | 显示全部楼层 |阅读模式

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

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

×
Obtaining the Bounding Box of an AcDbSpline using ObjectARX

昨天贴了获得实体的包围盒的代码,今天贴个获得准确的SPLINE的ARX解决方案。

问题:

I want to get the bounding box of spline, but the getGeomExtents() functions does not return the expected results. How do I get a tighter bounding box for a spline?


解答:

The AcDbSpline does not return a "tight" bounding box when getGeomExtents() is used.

To get a tighter bounding box you need to calculate the bounding box yourself. You can make use of the function getPointAtParam() to traverse along the spline and check for the maximum/minimum x and y coordinates. The accuracy of the bounding box depends upon how finely the curve is divided and sampled. The division value of 1e6 gives a good accuracy and takes acceptable time to calculate. The functions pasted below shows how this can be done. The attached VC++ project has the complete code (with minimal error checking). Type command "SplineBB" and select a spline object. It will draw two bounding boxes. The red rectangle is the extents returned by the getGeomExtents() while the yellow rectangle is the calculated one.

Something like this:
游客,如果您要查看本帖隐藏内容请回复


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

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-12-5 21:34:45 来自手机 | 显示全部楼层
资料可能老了点,还不过时桌子的东西本来就云遮雾罩的
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 344个

财富等级: 日进斗金

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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-12-5 21:55:21 来自手机 | 显示全部楼层
spline是点描述实体,理论上应该是无限逼近,准确上没有极限
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 344个

财富等级: 日进斗金

发表于 2014-12-5 22:12:25 | 显示全部楼层
本帖最后由 牢固 于 2014-12-7 19:18 编辑

这个代码用的是模拟点法计算包围盒,还是不太精确,计算量也比较大!
我写的这个既精确又快!
  1. void getSplineBox (const AcDbSpline *pSpline,AcGePoint3d &minPt,AcGePoint3d &maxPt)
  2. {
  3.         AcDbExtents Ext;
  4.         AcGePoint3d p0,p1,p2,p3;
  5.         AcDbIntArray osnapModes,geomIds;
  6.         AcGePoint3dArray pt3ds;
  7.         pSpline->getGripPoints(pt3ds,osnapModes,geomIds);
  8.         for (int k = 0;k<pt3ds.length();k++)
  9.         {
  10.                 Ext.addPoint(pt3ds.at(k));
  11.         }
  12.         p0 = Ext.minPoint();
  13.         p2 = Ext.maxPoint();       double dis = 0.5 * (p2-p0).length();
  14.         p0.x = p0.x - dis;
  15.         p0.y = p0.y - dis;
  16.         p2.x = p2.x + dis;
  17.         p2.y = p2.y + dis;
  18.         p1.x = p0.x;
  19.         p1.y = p2.y;
  20.         p1.z = p0.z;
  21.         p3.x = p2.x;
  22.         p3.y = p0.y;
  23.         p3.z = p2.z;
  24.         AcGeVector3d vec0(1.0,0.0,0.0),vec1(0.0,-1.0,0.0),vec2(-1.0,0.0,0.0),vec3(0.0,1.0,0.0);
  25.         pSpline->getClosestPointTo(p0,vec0,p0,Adesk::kTrue);               
  26.         pSpline->getClosestPointTo(p1,vec1,p1,Adesk::kTrue);
  27.         pSpline->getClosestPointTo(p2,vec2,p2,Adesk::kTrue);
  28.         pSpline->getClosestPointTo(p3,vec3,p3,Adesk::kTrue);
  29.         AcDbExtents Ext1;
  30.         Ext1.addPoint(p0);
  31.         Ext1.addPoint(p1);
  32.         Ext1.addPoint(p2);
  33.         Ext1.addPoint(p3);
  34.         minPt = Ext1.minPoint();
  35.         maxPt = Ext1.maxPoint();
  36. }



点评

我理解你这个算法相当于先获得三维样条曲线四边包围盒(上下无盖的),这个包围盒俯视图看来是棱形的,然后通过这个棱形的再得到个平面矩形方形包围盒。不知道是不是这么理解。另外一开始获得的四个点往外偏0.5*对角线  详情 回复 发表于 2018-6-9 15:02

评分

参与人数 1威望 +1 D豆 +5 贡献 +3 收起 理由
Highflybird + 1 + 5 + 3

查看全部评分

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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-12-6 06:41:54 来自手机 | 显示全部楼层
本帖最后由 st788796 于 2014-12-6 06:44 编辑
牢固 发表于 2014-12-5 22:12
这个代码用的是模拟点法计算包围盒,还是不太精确,计算量也比较大!
我写的这个既精确又快!


这个好,那个lisp版本也可以获取controlPoints求pnts:box用做投影面

点评

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

使用道具 举报

已领礼包: 19个

财富等级: 恭喜发财

发表于 2014-12-6 10:44:09 | 显示全部楼层
st788796 发表于 2014-12-6 06:41
这个好,那个lisp版本也可以获取controlPoints求pnts:box用做投影面

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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-12-6 13:20:46 | 显示全部楼层
本帖最后由 st788796 于 2014-12-6 13:22 编辑
Lisphk 发表于 2014-12-6 10:44
大师,能讲讲什么原理吗?

G 版用的是这个函数

AcDbCurve::getClosestPointTo 函数

virtual Acad::ErrorStatus
getClosestPointTo(
const AcGePoint3d& givenPnt,
const AcGeVector3d& direction,
AcGePoint3d& pointOnCurve,
Adesk::Boolean extend = Adesk::kFalse) const;

givenPnt 输入点(WCS坐标中),用于找出曲线上的最近点
direction 输入法向矢量(WCS坐标中),用于平面投影
pointOnCurve 返回曲线上与givenPnt最近的点(WCS坐标中)
extend 输入布尔值,表示在搜索最近点时是否延伸曲线

此函数将曲线投影至由givenPnt和normal定义的平面,找出曲线上与givenPnt最近的点,再将这个最近点投影回原始曲线上并在pointOnCurve中返回结果。

如果extend == Adesk::kTrue,则曲线沿它的路径延伸以找出最近点。

如果成功则返回Acad::eOk。根据执行返回错误值。

在派生类中,此函数必须可以投影至由一个点(givenPnt)和一个法向矢量(normal)定义的平面上,如果需要可延伸曲线的投影,找出与givenPnt最近的点,再将这个找到的点投影回原始曲线上(如果被延伸则在它的路径上)并设置pointOnCurve为最终结果。

使用AcGe类可执行一些投影和最近点计算的工作。

如果操作成功,此函数返回Acad::eOk。错误的返回值根据错误和执行器。关于可能的ErrorStatus值列表,参见头文件acdh.h。

默认执行返回Acad::eNotImplemented。


先用一个较大方框作投影面,用函数找出曲线上距离投影面最近的点,四个边就求出四个点,然后由这四个点载找个 BOX

vlisp 对应函数是

在将曲线投影到平面上之后,返回曲线上的最近点(在 WCS 上)

(vlax-curve-getClosestPointToProjection curve-obj givenPnt normal[extend])
参数

curve-obj  要测量的 VLA 对象。
givenPnt   WCS 中的点,在曲线上寻找该点的最近点。
normal   WCS 中的法线矢量,指定投影平面。
extend   如果指定该参数且其值不为 nil,vlax-curve-getClosestPointToProjection 在搜索最近点时扩展曲线。

vlax-curve-getClosestPointToProjection 将曲线投影到由 givenPnt 和 normal 定义的平面上,然后在该平面上计算距 givenPnt 最近的点。然后,vlax-curve-getClosestPointToProjection 将结果点重新投影到原来的曲线上,并返回投影后的点。

返回值   如果成功,则返回表示曲线上一点的三维点表,否则返回 nil。

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

使用道具 举报

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

使用道具 举报

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

使用道具 举报

已领礼包: 157个

财富等级: 日进斗金

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

使用道具 举报

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

使用道具 举报

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

使用道具 举报

已领礼包: 3532个

财富等级: 富可敌国

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

使用道具 举报

已领礼包: 38个

财富等级: 招财进宝

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-5 00:09 , Processed in 0.496161 second(s), 56 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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