OpenCASCADE 平面求交

eryar@163.com

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 平面求交的更多相关文章

  1. OpenCASCADE直线与平面求交

    OpenCASCADE直线与平面求交 在<解析几何>相关的书中都给出了直线和平面的一般方程和参数方程.其中直线的一般方程有点向式形式的. 由于过空间一点可作且只能作一条直线平行于已知直线, ...

  2. OpenCASCADE圆与平面求交

    OpenCASCADE圆与平面求交 eryar@163.com 在 解析几何求交之圆与二次曲面中分析了OpenCASCADE提供的类IntAna_IntConicQuad可以用来计算圆与二次曲面之间的 ...

  3. 一步一步实现基于GPU的pathtracer(二):求交算法

    不管是哪种全局光照算法,最根本的都要落实到光线与物体的求交.主要分为光线与参数曲面和非参数曲面的求交,典型的参数曲面有球.盒.圆柱等基本体及基本体的组合体,以及一些更为复杂的参数曲面.非参数曲面就是所 ...

  4. OpenCASCADE 平面与球面求交

    OpenCASCADE 平面与球面求交 eryar@163.com OpenCASCADE提供了类IntAna_QuadQuadGeo用来计算两个二次曲面quadric(球面.圆柱面.圆锥面及平面,平 ...

  5. 光线求交-面、三角形、球 (Ray intersection)

    光线求交 光线定义:position \(a(t)\) = \(o\) + \(t\vec{d}\); 球定义: center p, radius r; 平面定义:normal \(\vec{n}\) ...

  6. ray与triangle/quad求交二三事

    引擎中,ray与quad求交,算法未细看,但有求解二次方程,不解.ray与triangle求交,使用的是97年经典算法,仔细看过论文,多谢小武同学指点,用到了克拉默法则求解线性方程组.想模仿该方法,做 ...

  7. [NetTopologySuite](2)任意多边形求交

    任意多边形求交: private void btnPolygon_Click(object sender, EventArgs e) { , , , , , , , , , , , , , }; , ...

  8. HDU - 3982:Harry Potter and J.K.Rowling(半平面交+圆与多边形求交)(WA ing)

    pro:给定一枚蛋糕,蛋糕上某个位置有个草莓,寿星在上面切了N刀,最后寿星会吃含有草莓的那一块蛋糕,问他的蛋糕占总蛋糕的面积比. sol:显然需要半平面交求含有蛋糕的那一块,然后有圆弧,不太方便求交. ...

  9. hdu 5111 树上求交

    hdu 5111 树上求交(树链剖分 + 主席树) 题意: 给出两棵树,大小分别为\(n1\),\(n2\), 树上的结点权值为\(weight_i\) 同一棵树上的结点权值各不相同,不同树上的结点权 ...

随机推荐

  1. ubuntu自带截图工具

    ubuntu自带的截图工具感觉能够满足基本的截图功能,可以不必安装另外的截图软件. 一般用到的截图类型有三种:全屏.当前活动窗口.自定义区域,其中自定义区域截图是最灵活也是我们用的最多的方式.在ubu ...

  2. 笔记:Python防止SQL注入

    非安全的方式,使用动态拼接SQL 输入' or 1 = 1 or '1 sql ="""SELECT * FROM goods WHERE name = '%s';&qu ...

  3. kaggle 实战 (2): CNN 手写数字识别

    文章目录 Tensorflow 官方示例 CNN 提交结果 Tensorflow 官方示例 import tensorflow as tf mnist = tf.keras.datasets.mnis ...

  4. 数据库MySQL--基础查询

    1.查询字段 查询表某字段:select 字段名 from 表名: 查询表内所有字段:select * from 表名: (当字段和关键字重名是用( ` )着重号区分 ) 2.查询常量值 select ...

  5. CSS3——伸缩布局及应用

    CSS3在布局方面做了非常大的改进,使得我们对块级元素的布局排列变得十分灵活,适应性非常强,其强大的伸缩性,在响应式开中可以发挥极大的作用. 主轴:Flex容器的主轴主要用来配置Flex项目,默认是水 ...

  6. 服务器断过一次电之后,mysql启动不了了

    公司内部服务器,周末会直接拉闸断电,之前也没问题,但这次回来发现mysql启动不了了. service mysqld start 提示: Starting MySQL.The server quit ...

  7. 海量数据解决思路之Hash算法

    海量数据解决思路之Hash算法   一.概述 本文将粗略讲述一下Hash算法的概念特性,里边会结合 分布式系统负载均衡 实例对Hash的一致性做深入探讨.另外,探讨一下Hash算法在海量数据处理方案中 ...

  8. Delphi THashedStringList用法

    Delphi中的THashedStringList对象 Delphi在在IniFiles 单元中定义了THashedStringList类: THashedStringList = class(TSt ...

  9. 正则表达式r和re

    # coding:utf-8 import re print 'a\ws' print r'a\nb' # r'': 一般用在正则表达式中,称为原始字符串,作用是将Python语法中的反斜杠转义给 取 ...

  10. ASP.NET的Validform验证表单使用说明

    当我们写提交表单的时候往往需要验证表单是否填写了内容,是否正确,这个插件可以很方便的完成我们需要的验证! 使用方法: 1.引用JS <script type="text/javascr ...