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\) 同一棵树上的结点权值各不相同,不同树上的结点权 ...
随机推荐
- R:ggplot2数据可视化——进阶(3)
Part 3: Top 50 ggplot2 Visualizations - The Master List, 结合进阶1.2内容构建图形 有效的图形是: 不扭曲事实 传递正确的信息 简洁优雅 美观 ...
- 24-Ubuntu-文件和目录命令-查找文件内容-grep
grep Linux系统中grep命令是一种强大的文本搜索工具. grep允许文本文件进行模式查找,所谓模式查找,又被称为正则表达式. 选项 含义 -n 显示匹配行及行号 -v 显示不包括匹配文本的所 ...
- 【POJ】1502 MPI Maelstrom
题目链接:http://poj.org/problem?id=1502 题意:一个处理器给n-1个处理器发送广播,问最短时间.广播时并发,也就是各个路径就大的一方.输入如果是x的话说明两个处理器不能相 ...
- 【POJ】3278 Catch That Cow
题目链接:http://poj.org/problem?id=3278 题意:有一头奶牛跑到了K的位置,农夫在N的位置,求最短抓到奶牛的时间. 农夫有两种移动方式. 1.步行:一分钟内从x->x ...
- iOS开发系列-Category
Category Category是OC中特有的语法.Category的作用 * 可以在不修改原来类的基础上,为这个类扩充一些方法 * 一个庞大的类可以分为多个模块开发 * 一个庞大的类可以由多个人来 ...
- FTP、SFTP、SCP、SSH、OpenSSH关系解密
FTP(File Transfer Protocol):是TCP/IP网络上两台计算机传送文件的协议,FTP是在TCP/IP网络和INTERNET上最早使用的协议之一,它属于网络协议组的应用层.FTP ...
- sql (8) AVG
SQL avg 语法SELECT AVG(column_name) FROM table_name新建表:StudentS S_id Grade Name phone1 98 小明 1234562 9 ...
- CodeForces - 803F
http://codeforces.com/problemset/problem/803/F #include <iostream> #include <cstdio> #in ...
- nginx反向代理时有无”/”的辨析
nginx反向代理是日常使用nginx时最常用到的功能之一.在配置url的过程中,“/”的有无经常是影响我们配置成功的关键,也是困扰我们的问题所在.在此,结合实际例子,作简要辨析. 场景一:利用根目录 ...
- 阿里云启动视频云V5计划,全面赋能生态合作伙伴
9月25 - 27日,主题为数·智的2019云栖大会在杭州举行.在第三天的智能视频云专场中,阿里云研究员金戈首次对外发布视频云V5计划,释放视频IT基础设施红利,赋能生态合作伙伴,共促大视频产业发展. ...