OpenCASCADE 平面求交
OpenCASCADE 平面求交
OpenCASCADE提供了类IntAna_QuadQuadGeo用来计算两个二次曲面quadric(球面、圆柱面、圆锥面及平面,平面是二次曲面的特例)之间的交线。他们之间可能的结果有:
l 一个点
l 一条或两条直线
l 一个点和一条直线
l 圆
l 椭圆
l 抛物线
l 双曲线

将源码结合《高等数学》、《解析几何》等书,可以来学习如何将理论付诸实践。本文主要介绍这个类中两个平面求交的源码实现。从源码中也可以看出OpenCASCADE官方开发人员的编码习惯。

将源码列出如下:
void IntAna_QuadQuadGeo::Perform (const gp_Pln& P1,
const gp_Pln& P2,
const Standard_Real TolAng,
const Standard_Real Tol)
{
Standard_Real A1, B1, C1, D1, A2, B2, C2, D2, dist1, dist2, aMVD;
//
done=Standard_False;
param2bis=.;
//
P1.Coefficients(A1,B1,C1,D1);
P2.Coefficients(A2,B2,C2,D2);
//
gp_Vec aVN1(A1,B1,C1);
gp_Vec aVN2(A2,B2,C2);
gp_Vec vd(aVN1.Crossed(aVN2));
//
const gp_Pnt& aLocP1=P1.Location();
const gp_Pnt& aLocP2=P2.Location();
//
dist1=A2*aLocP1.X() + B2*aLocP1.Y() + C2*aLocP1.Z() + D2;
dist2=A1*aLocP2.X() + B1*aLocP2.Y() + C1*aLocP2.Z() + D1;
//
aMVD=vd.Magnitude();
if(aMVD <=TolAng) {
// normalles are collinear - planes are same or parallel
typeres = (Abs(dist1) <= Tol && Abs(dist2) <= Tol) ? IntAna_Same
: IntAna_Empty;
}
else {
Standard_Real denom, denom2, ddenom, par1, par2;
Standard_Real X1, Y1, Z1, X2, Y2, Z2, aEps;
//
aEps=.e-;
denom=A1*A2 + B1*B2 + C1*C2;
denom2 = denom*denom;
ddenom = . - denom2; denom = ( Abs(ddenom) <= aEps ) ? aEps : ddenom; par1 = dist1/denom;
par2 = -dist2/denom; gp_Vec inter1(aVN1.Crossed(vd));
gp_Vec inter2(aVN2.Crossed(vd)); X1=aLocP1.X() + par1*inter1.X();
Y1=aLocP1.Y() + par1*inter1.Y();
Z1=aLocP1.Z() + par1*inter1.Z();
X2=aLocP2.X() + par2*inter2.X();
Y2=aLocP2.Y() + par2*inter2.Y();
Z2=aLocP2.Z() + par2*inter2.Z(); pt1=gp_Pnt((X1+X2)*0.5, (Y1+Y2)*0.5, (Z1+Z2)*0.5);
dir1 = gp_Dir(vd);
typeres = IntAna_Line;
nbint = ;
//
//-------------------------------------------------------
// When the value of the angle between the planes is small
// the origin of intersection line is computed with error
// [ ~0.0001 ] that can not br considered as small one
// e.g.
// for {A~=2.e-6, dist1=4.2e-5, dist2==1.e-4} =>
// {denom=3.4e-12, par1=12550297.6, par2=32605552.9, etc}
// So,
// the origin should be refined if it is possible
//
Standard_Real aTreshAng, aTreshDist;
//
aTreshAng=.e-; // 1.e-4 deg
aTreshDist=.e-;
//
if (aMVD < aTreshAng) {
Standard_Real aDist1, aDist2;
//
aDist1=A1*pt1.X() + B1*pt1.Y() + C1*pt1.Z() + D1;
aDist2=A2*pt1.X() + B2*pt1.Y() + C2*pt1.Z() + D2;
//
if (fabs(aDist1)>aTreshDist || fabs(aDist2)>aTreshDist) {
Standard_Boolean bIsDone, bIsParallel;
IntAna_IntConicQuad aICQ;
//
// 1.
gp_Dir aDN1(aVN1);
gp_Lin aL1(pt1, aDN1);
//
aICQ.Perform(aL1, P1, TolAng, Tol);
bIsDone=aICQ.IsDone();
if (!bIsDone) {
return;
}
//
const gp_Pnt& aPnt1=aICQ.Point();
//----------------------------------
// 2.
gp_Dir aDL2(dir1.Crossed(aDN1));
gp_Lin aL2(aPnt1, aDL2);
//
aICQ.Perform(aL2, P2, TolAng, Tol);
bIsDone=aICQ.IsDone();
if (!bIsDone) {
return;
}
//
bIsParallel=aICQ.IsParallel();
if (bIsParallel) {
return;
}
//
const gp_Pnt& aPnt2=aICQ.Point();
//
pt1=aPnt2;
}
}
}
done=Standard_True;
}
要理解这个源码,需要知道平面的一般方程:Ax+By+Cz+D=0,两个平面之间的夹角等概念。通过源码,可以看出计算两个平面之间的交线的步骤如下:
l 获取两个平面的一般方程的系数:A、B、C、D,其中平面的法向量(A,B,C)为单位向量;
l 将两个平面的法向量叉乘得到的向量vd为平面交线的方向;
l 分别计算一个平面上的点到另外一个平面的距离:dist1和dist2;
l 如果向量vd的大小小于指定的精度TolAng,则认为两个平面平行没有交线;如果两个距离dist1和dist2小于指定的精度Tol,则认为两个平面是相同的(重合);
l 计算两个平面的夹角denom;
l 根据两个平面的夹角计算交线上的点;
l 后面是处理两个平面夹角很小的情况;
l 最后得到交线上的点pt1和方向dir1
其实上面求交线上点的代码不好理解,可以换成三个平面求交点的处理更好理解,如将交线的方向作为法向得到的一个平面与那两个平面一起计算交点,这个交点就一定在交线上,相关代码如下:
gp_Pln P3(vd.X(), vd.Y(), vd.Z(), 0.0); IntAna_Int3Pln aTool(P1, P2, P3);
if (aTool.IsDone())
{
pt1 = aTool.Value();
}
因为三个平面求交点是用高斯消元法解三元一次方程组,性能没有上面的代码好。生活中到处都是选择题,如何抉择是个问题啊。
OpenCASCADE 平面求交的更多相关文章
- OpenCASCADE直线与平面求交
OpenCASCADE直线与平面求交 在<解析几何>相关的书中都给出了直线和平面的一般方程和参数方程.其中直线的一般方程有点向式形式的. 由于过空间一点可作且只能作一条直线平行于已知直线, ...
- OpenCASCADE圆与平面求交
OpenCASCADE圆与平面求交 eryar@163.com 在 解析几何求交之圆与二次曲面中分析了OpenCASCADE提供的类IntAna_IntConicQuad可以用来计算圆与二次曲面之间的 ...
- 一步一步实现基于GPU的pathtracer(二):求交算法
不管是哪种全局光照算法,最根本的都要落实到光线与物体的求交.主要分为光线与参数曲面和非参数曲面的求交,典型的参数曲面有球.盒.圆柱等基本体及基本体的组合体,以及一些更为复杂的参数曲面.非参数曲面就是所 ...
- OpenCASCADE 平面与球面求交
OpenCASCADE 平面与球面求交 eryar@163.com OpenCASCADE提供了类IntAna_QuadQuadGeo用来计算两个二次曲面quadric(球面.圆柱面.圆锥面及平面,平 ...
- 光线求交-面、三角形、球 (Ray intersection)
光线求交 光线定义:position \(a(t)\) = \(o\) + \(t\vec{d}\); 球定义: center p, radius r; 平面定义:normal \(\vec{n}\) ...
- ray与triangle/quad求交二三事
引擎中,ray与quad求交,算法未细看,但有求解二次方程,不解.ray与triangle求交,使用的是97年经典算法,仔细看过论文,多谢小武同学指点,用到了克拉默法则求解线性方程组.想模仿该方法,做 ...
- [NetTopologySuite](2)任意多边形求交
任意多边形求交: private void btnPolygon_Click(object sender, EventArgs e) { , , , , , , , , , , , , , }; , ...
- HDU - 3982:Harry Potter and J.K.Rowling(半平面交+圆与多边形求交)(WA ing)
pro:给定一枚蛋糕,蛋糕上某个位置有个草莓,寿星在上面切了N刀,最后寿星会吃含有草莓的那一块蛋糕,问他的蛋糕占总蛋糕的面积比. sol:显然需要半平面交求含有蛋糕的那一块,然后有圆弧,不太方便求交. ...
- hdu 5111 树上求交
hdu 5111 树上求交(树链剖分 + 主席树) 题意: 给出两棵树,大小分别为\(n1\),\(n2\), 树上的结点权值为\(weight_i\) 同一棵树上的结点权值各不相同,不同树上的结点权 ...
随机推荐
- Red and Black 模板题 /// BFS oj22063
题目大意: Description There is a rectangular room, covered with square tiles. Each tile is colored eithe ...
- USACO2006 Backward Digit Sums /// 全排列 oj24212
题目大意: 给出杨辉三角的顶点值M和底边数的个数 N (1 ≤ N ≤ 10) ,求出底边各个数的值,其中各个数范围都为1 ~ N 当N=4,M=16时可能是这样的 3 1 2 4 ...
- python接口自动化(接口基础)
一.什么是接口? 前端负责展示和收集数据 后端负责处理数据,返回对应的结果 接口是前端与后端之间的桥梁,传递数据的通道 二.
- shell 命令 用户管理
1. 查看保存用户相关信息的文件 [ cat /etc/passwd ] [linux : x : 1000 : 1000 : linux,,, : ...
- postman在有登录认证的情况下进行接口测试!!!
1.启动自己的项目之后直接使用浏览器进行登录,登陆之后随意点击一个请求,F12找到该请求中请求头的Cookie键值对. 2.将该键值对复制粘贴到postman中的请求Headers中,如下图. 3,请 ...
- IPsec分析/测试/
一 局域网拓扑图 局域网环境搭建步骤: (升级最新版本 ,恢复出厂设置后) 1 两台网关wan口直连,分别接两台pc , 2 局域网网络测试,正常情况下PC1 和PC2 互通 ,测试通过在进行ip ...
- flutter中的BuildContext
https://www.jianshu.com/p/509b77b26b78
- Vue Virtual Dom 和 Diff原理(面试必备) 极简版
我又来了,这是Vue面试三板斧的最后一招,当然也是极其简单了,先说Virtual Dom,来一句概念: 用js来模拟DOM中的节点.传说中的虚拟DOM. 再来一张图: 是不是一下子秒懂 没懂再来一张 ...
- Grunt入门
Grunt 新手一日入门 2014.06.20 前端相关 TOC 1. 用途和使用场景 2. 开发一个任务自动处理器 3. 开始学习 Grunt 3.1. 安装 Grunt 3.2. 生成 packa ...
- ON_EVENT 报错
错误提示: error C2440: 'initializing' : cannot convert from 'const wchar_t [1]' to 'UINT' error C2440: ' ...