问题:

如果有这样的场景:已知一条B样条曲线,已知曲线上一个点,求过这个点的曲线的切线或法线,在OpenCasCade中如何解决?

局限性

实际上,上述求解是不存在的,或者说直接获得过这个点的曲线的法向或切向量的方法是没有的,原因之一可能是安全性考虑,比如所给点不在曲线上?虽然用户可能说我这个点就在曲线上,但是参数化的曲线可不管你怎么说。
在OpenCasCade中,要获得一条参数曲线的某个位置的法向或切向量,只能通过这个位置的参数u来实现。既然这样,那有没有什么办法可以先获得这个点的参数u,然后再将这个参数u作为自变量传递给曲线进行计算这个位置的法向或且想?

可行方法

OpenCasCade中有内置的功能是将某个点投射到曲线上,相关的类为

GeomAPI_ProjectPointOnCurve

实际上是找这个点到这条曲线上哪个点能获得最小距离或最大距离,能够获得投射点的坐标和其他变量,包括这个点的参数u。通过这个u就可以重新计算这个点的坐标(算是一种修正吧)和这个点的切向量。

实例

下图所示为一条分段Bezier曲线,白色点为各个控制点,需要在第三个控制点上画一条曲线的切线。虽然这个控制点一定在曲线上,但是参数型的曲线并不能确定某个点是否一定在曲线上或者有多大的误差。此时可以将该点投影到曲线上,获得曲线上最近的点和最远的点,如果添加一条判断语句,比如投影点与原点距离小于某个极小值,就可筛选出该点,同时可以获得该点对应的参数u。示意图如下所示:

相关代码片段如下:

    AIS_ListOfInteractive aList;myAISContext->DisplayedObjects(aList);AIS_ListIteratorOfListOfInteractive aListIterator;for(aListIterator.Initialize(aList);aListIterator.More();aListIterator.Next()){myAISContext->Remove (aListIterator.Value(), Standard_False);}TColgp_Array1OfPnt Poles(1,9);Poles.SetValue(1, gp_Pnt(0,-10,0));Poles.SetValue(2, gp_Pnt(0,-10,5));Poles.SetValue(3, gp_Pnt(0,-5,5));Poles.SetValue(4, gp_Pnt(0,0,5));Poles.SetValue(5, gp_Pnt(0,0,0));Poles.SetValue(6, gp_Pnt(0,0,-5));Poles.SetValue(7, gp_Pnt(0,5,-5));Poles.SetValue(8, gp_Pnt(0,10,-5));Poles.SetValue(9, gp_Pnt(0,10,0));TColStd_Array1OfReal PolesWeight(1,9);PolesWeight.SetValue(1, 1.0);PolesWeight.SetValue(2, 0.707);PolesWeight.SetValue(3, 1.0);PolesWeight.SetValue(4, 0.707);PolesWeight.SetValue(5, 1.0);PolesWeight.SetValue(6, 0.707);PolesWeight.SetValue(7, 1.0);PolesWeight.SetValue(8, 0.707);PolesWeight.SetValue(9, 1.0);for(int i=0; i<9; ++i){TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(Poles.Value(i+1));Handle(AIS_Shape) vert = new AIS_Shape(aVertex);myAISContext->SetColor(vert,Quantity_NOC_WHITE,Standard_False); myAISContext->Display(vert,Standard_False);}Fit();Standard_Integer curtype = 3;if(curtype == 1){}else if(curtype == 2){}else if(curtype == 3){/// 分段Bezier曲线Standard_Integer degree(2);Standard_Integer PNum = 9;Standard_Integer KNum = PNum - 4;TColStd_Array1OfReal knots(1,KNum);for(int i=0; i<KNum; ++i){knots.SetValue(i+1, i);}TColStd_Array1OfInteger mults(1,KNum);for(int i=0; i<KNum; ++i){if(i == 0 || i == KNum-1){mults.SetValue(i+1, degree+1);}else{mults.SetValue(i+1, degree);}}Handle(Geom_BSplineCurve) curve = new Geom_BSplineCurve(Poles, knots, mults, degree);TopoDS_Edge ed1 = BRepBuilderAPI_MakeEdge(curve);TopoDS_Wire wr1 = BRepBuilderAPI_MakeWire(ed1);Handle(AIS_Shape) red = new AIS_Shape(wr1);myAISContext->SetColor(red,Quantity_NOC_RED,Standard_False); myAISContext->Display(red,Standard_False);Fit();gp_Pnt N, Q, P(0, -5, 5);gp_Pnt PntOnCurve;Standard_Real distance;Standard_Real param_u;GeomAPI_ProjectPointOnCurve PPC(P, curve);N = PPC.NearestPoint();Standard_Integer NbResults = PPC.NbPoints();if(NbResults > 0){for(Standard_Integer i=1; i<NbResults+1; ++i){Q = PPC.Point(i);distance = PPC.Distance(i);Standard_Real u = PPC.Parameter(i);std::cout << "projected point:" << Q.X() << " " << Q.Y() << " " << Q.Z() << std::endl;std::cout << "distance:" << distance << std::endl;std::cout << "parameter:" << u << std::endl;if(distance < 1E-12){PntOnCurve.SetCoord(Q.X(), Q.Y(), Q.Z());param_u = u;}}}std::cout << "projected point:" << PntOnCurve.X() << " " << PntOnCurve.Y() << " " << PntOnCurve.Z() << std::endl;gp_Vec tang;curve->D1(param_u, P, tang);Handle(ISession_Direction) aDirection1 = new ISession_Direction(P,tang);myAISContext->Display(aDirection1, Standard_False);}else{}

OpenCasCade——给定B样条曲线上的一点,求出过该点的切向量或法向量相关推荐

  1. unity 求出物体所在相机的横截面 解决调整 field Of View后场景物体和UI不匹配

    接着上一篇来 Unity UI上的物体跟随场景物体位置变化而变化(人物血条/称号) 上一篇写了血条跟随角色变化  写完之后 我需要用相机的 field Of View 功能做一个远近景切换的功能 然后 ...

  2. 已知长短轴求椭圆上任意一点的坐标_高中数学必修2:平面解析几何——椭圆(经典习题)...

    今天接着给大家分享关于高中数学必修2平面解析几何中椭圆知识点讲解,从三个方面进行讲解:基础梳理.要点整理.经典高考习题解题过程及答案. 一.基础梳理 1.椭圆的定义 2.椭圆的标准方程和几何性质 要点 ...

  3. c语言辗转相除法求最大公约数_趣味探究:妙法求“最大公因数”,比书上难一点,你敢挑战吗?(适合56年级)...

    [题记] 宝石虽落在泥土里,仍是宝石,砂粒虽被吹到天空中,还是砂粒.--莎士比亚不是有水的地方就有青蛙,但是青蛙叫的地方必定有水.--歌德 [配合教材]本探究配合"因数与倍数".通 ...

  4. 网易之小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性.需要根据给定的w,x,y,z,求出集合中一共有多少个元素。

    import java.util.HashSet; import java.util.Scanner; import java.util.Set;/*** 小易最近在数学课上学习到了集合的概念,集合有 ...

  5. 编程笔试(解析及代码实现):求出一个整数中各位数上所包含全部质数之和

    编程笔试(解析及代码实现):求出一个整数中各位数上所包含全部质数之和 目录 题目描述 代码实现 题目描述 求出一个整数中各位数上所包含全部质数之和 一家电子商务公司计划在圣诞节给客户提供特别折扣,他们 ...

  6. C语言编程>第二十周 ② 下列给定程序中,函数fun的功能是:求出数组中最大数和次最大数,并把最大数和b[0]中的数对调、次最大数和b[1]中的数对调。

    例题:下列给定程序中,函数fun的功能是:求出数组中最大数和次最大数,并把最大数和b[0]中的数对调.次最大数和b[1]中的数对调. 注意:不要改动main函数,不能增行或删行,也不能更改程序的结构. ...

  7. c++ 已知直线外一点,求对称点

    下面通过两种直线方程的形式,求解点关于直线的距离.垂足.对称点公式. 问题描述1: 已知点的坐标(x0,y0),直线的方程为Ax+By+C = 0: 求点到直线上的距离d.点在直线上的垂足(x, y) ...

  8. 给定一个n*m矩阵,求从左上角到右下角走的项目3个问题?

    这个问题中走矩阵的格子还是定点是不一样的. 这里给出两个解法. 题目1:给定一个n*m矩阵,求从左上角格子到右下角格子总共存在多少条路径,每次只能向右走或者向下走. # 题目1:给定一个n*m矩阵,求 ...

  9. c语言给定整数求紧随素数,C语言:找出一个大于给定整数m且紧随m的素数,-求出能整除x且不是偶数的数的个数,...

    //函数fun功能:找出一个大于给定整数m且紧随m的素数,并作为函数值返回. #include #include #include int fun( int m) { int i,k; for (i= ...

  10. 过椭圆外一点引两条切线方程_过椭圆上任意一点的切线方程引发的思考与结论...

    过椭圆上任意一点的切线方程引发的思考与结论 邓魁甲 江西省赣州市第三中学 341000 最近笔者在讲授高三第一轮复习时遇见复习资料上一个题目:过椭圆外一点 向椭圆 作切线,与椭圆切于 两点,可知经过 ...

最新文章

  1. C笔记(2014-12备份)
  2. 革命性提升-宇宙最强的NLP预训练BERT模型(附官方代码)
  3. [BZOJ1222/Luogu2224][HNOI2001]产品加工
  4. Android 动画AlphaAnimation类方法
  5. 【python】os.getcwd和getcwdu
  6. 解决-ubuntu 安装redis无法启动
  7. RDS SQL Server - 专题分享 - 巧用执行计划缓存之Table Scan
  8. 5.VMware View 5.0安装与部署-安装view agent与模版
  9. springmvc源码 - handlerAdapter是如何初始化的
  10. 预测算法用java实现
  11. Android 网络下载文件 图片 httpurl
  12. ipad触屏失控出现乱跳
  13. python clicknium 微信发送消息以及获取好友列表
  14. 【SSH框架/国际物流商综平台】-03 部门、用户、角色、模块 CURD BRAC认证 细粒度权限控制 BaseAction Page struts.xml *.hbm.xml
  15. 小猿圈分享适合零基础学python的书籍
  16. 2022-09-12-kvm介绍
  17. 仿写微信公众号添加自定义菜单 并给后台存数据
  18. PPT 如何取消幻灯片自动播放
  19. 牛客小白月赛21 J.Jelly
  20. 【C++】C/C++内存管理

热门文章

  1. matlab 线性分析,线性系统稳定性分析的MATLAB分析方法.doc
  2. 微信支付:手机系统自带的浏览器,调用微信支付如何实现(非扫码)
  3. 自媒体学习教程 新手怎么开始学习自媒体
  4. 点击click触发两次事件解决办法
  5. mindoc源码编译和部署
  6. 用友U8打开起初采购入库单报错
  7. 变废为宝,用旧电脑自己DIY组建 NAS 服务器
  8. win10专业版激活
  9. QTDesigner简介
  10. “算法分析与设计”课程设计:回溯法解决八皇后问题并可视化输出(Python实现)