XDSoft 发表于 2014-12-5 20:33:14

(3)获得AcDbSpline准确的包围盒

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:
**** Hidden Message *****

st788796 发表于 2014-12-5 21:34:45

资料可能老了点,还不过时桌子的东西本来就云遮雾罩的

牢固 发表于 2014-12-5 21:47:19

回复学习!{:soso_e179:}

st788796 发表于 2014-12-5 21:55:21

spline是点描述实体,理论上应该是无限逼近,准确上没有极限

牢固 发表于 2014-12-5 22:12:25

本帖最后由 牢固 于 2014-12-7 19:18 编辑

这个代码用的是模拟点法计算包围盒,还是不太精确,计算量也比较大!
我写的这个既精确又快!
void getSplineBox (const AcDbSpline *pSpline,AcGePoint3d &minPt,AcGePoint3d &maxPt)
{
      AcDbExtents Ext;
      AcGePoint3d p0,p1,p2,p3;
      AcDbIntArray osnapModes,geomIds;
      AcGePoint3dArray pt3ds;
      pSpline->getGripPoints(pt3ds,osnapModes,geomIds);
      for (int k = 0;k<pt3ds.length();k++)
      {
                Ext.addPoint(pt3ds.at(k));
      }
      p0 = Ext.minPoint();
      p2 = Ext.maxPoint();       double dis = 0.5 * (p2-p0).length();
      p0.x = p0.x - dis;
      p0.y = p0.y - dis;
      p2.x = p2.x + dis;
      p2.y = p2.y + dis;
      p1.x = p0.x;
      p1.y = p2.y;
      p1.z = p0.z;
      p3.x = p2.x;
      p3.y = p0.y;
      p3.z = p2.z;
      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);
      pSpline->getClosestPointTo(p0,vec0,p0,Adesk::kTrue);               
      pSpline->getClosestPointTo(p1,vec1,p1,Adesk::kTrue);
      pSpline->getClosestPointTo(p2,vec2,p2,Adesk::kTrue);
      pSpline->getClosestPointTo(p3,vec3,p3,Adesk::kTrue);
      AcDbExtents Ext1;
      Ext1.addPoint(p0);
      Ext1.addPoint(p1);
      Ext1.addPoint(p2);
      Ext1.addPoint(p3);
      minPt = Ext1.minPoint();
      maxPt = Ext1.maxPoint();
}


st788796 发表于 2014-12-6 06:41:54

本帖最后由 st788796 于 2014-12-6 06:44 编辑

牢固 发表于 2014-12-5 22:12
这个代码用的是模拟点法计算包围盒,还是不太精确,计算量也比较大!
我写的这个既精确又快!

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

Lisphk 发表于 2014-12-6 10:44:09

st788796 发表于 2014-12-6 06:41
这个好,那个lisp版本也可以获取controlPoints求pnts:box用做投影面

大师,能讲讲什么原理吗?

st788796 发表于 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)
参数

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

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

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

wzg356 发表于 2014-12-6 18:24:37

到这儿来收获不小,感动

why1025 发表于 2014-12-13 13:41:16

看看代码!!!!!!!!!!!!!

gis2000 发表于 2014-12-18 19:53:48

谢谢分享!

cxjzxf 发表于 2015-1-17 19:53:06

有什么好的方法,学习下。

1425361224 发表于 2015-5-8 14:05:09

我是来学习的,同志们

yfy2003 发表于 2015-5-8 21:55:32

回复学习!

llq_78 发表于 2015-5-10 10:52:18

获得AcDbSpline准确的包围盒
页: [1] 2 3 4
查看完整版本: (3)获得AcDbSpline准确的包围盒