几何内核开发-实现自己的NURBS曲线生成API

2024-06-24 05:20

本文主要是介绍几何内核开发-实现自己的NURBS曲线生成API,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我去年有一篇帖子,介绍了NURBS曲线生成与显示的实现代码。

https://blog.csdn.net/stonewu/article/details/133387469?spm=1001.2014.3001.5501文章浏览阅读323次,点赞4次,收藏2次。搞3D几何内核算法研究,必须学习NURBS样条曲线曲面。看《非均匀有理B样条 第2版》这本书,学习起来,事半功倍。在《插件化算法研究平台》上,做了一个样条曲线研究功能,可以分析Bezier曲线、BSpline、NURBS曲线的各种性质,有直观的体验,能更好地理解。https://blog.csdn.net/stonewu/article/details/133387469?spm=1001.2014.3001.5501

本贴子介绍如何在OGG几何内核上做个自己NURBS曲线API。

曲线代码框架参考示例如下:(具体实现代码,请参考我去年的帖子自行实现,或联系本人)

namespace stone
{using namespace std;
class Point3
{
public:float x, y, z;Point3(float x = 0, float y = 0, float z = 0) : x(x), y(y), z(z) {}double norm() { return sqrt(x * x + y * y + z * z); }Point3 operator*(double d) { return Point3(x * d, y * d, z * d); }Point3 operator+(const Point3& p) { return Point3(x + p.x, y + p.y, z + p.z); }
};
class BaseCurve
{
public:virtual ~BaseCurve() {}BaseCurve(double precision) { m_precision = precision; }bool finished = false; //完成控制点构成bool m_mousePressed = false;int  m_currentControlPointIndex = -1;double         m_precision = 0.01; //精度vector<Point3> controlPoints;vector<Point3> curvePoints;//nurbs参数vector<double> weights;    //权重vector<double> knots;      // 结点向量int            degree = 3; // 曲线次数virtual void clear(){//清空curvePoints.clear();//清空controlPoints.clear();finished = false;}virtual void curveInfo() = 0;virtual void createCurve() = 0;virtual void appendControlPoint(Point3 controlPoint) { controlPoints.push_back(controlPoint); }virtual void moveControlPoint(int index, Point3 controlPoint) { controlPoints[index] = controlPoint; }void initKnots(){。。。}void initWeights(){。。。}
};
class BezierCurve : public BaseCurve
{
public:BezierCurve(double precision = 0.01) : BaseCurve(precision){};public:void curveInfo() { debugx("BezierCurve!"); }// 生成N阶贝塞尔曲线点void createCurve(){curveInfo();if (controlPoints.size() <= 1)return;//清空curvePoints.clear();auto size = controlPoints.size();for (double t = 0; t < 1.0000; t += m_precision){ //根据精度绘制点。。。}}
};class BSplineCurve : public BaseCurve
{
public:void curveInfo() { debugx("BSplineCurve!"); }BSplineCurve(int aDegree, double precision) : BaseCurve(precision) { degree = aDegree; }BSplineCurve(vector<Point3> points, int k, double precision) : BaseCurve(precision){controlPoints = points;degree = k;// 初始化结点向量, m = n + 1+ k   ,m+1节点数量, n+1控制点数量 ,k 次数。。。}// 计算基函数值double basis(int i, int k, double u){
。。。return a * basis(i, k - 1, u) + b * basis(i + 1, k - 1, u);}// 计算样条曲线上的点virtual Point3 calculatePoint(double u){Point3 result;。。。return result;}void createCurve(){curveInfo();//清空curvePoints.clear();auto size = controlPoints.size();if (size < 2)return;//生成NURBS曲线上所有的点。。。}void moveControlPoint(int index, Point3 controlPoint){controlPoints[index] = controlPoint;if (controlPoints.size() < 2)return;createCurve();}
};class NURBSCurve : public BSplineCurve
{
public:void curveInfo() override { debugx("NURBSCurve!"); }NURBSCurve(int aDegree=3, double precision = 0.01) : BSplineCurve(aDegree, precision) {}// 计算样条曲线上的点Point3 calculatePoint(double u) override{。。。return result;}
};
} //namespace stonenamespace stone
{class CurveUtil
{
public:static BRepBuilderAPI_MakePolygon CreateBezierCurve(TColgp_Array1OfPnt Array1, double precision = 0.01){。。}static BRepBuilderAPI_MakePolygon CreateNURBSCurve(TColgp_Array1OfPnt Array1, int aDegree=3, double precision = 0.01){。。。return makePolygon;}
};} //namespace stone MakeAPI

调用代码参考示例:

主要功能Demo:

1、定义5个控制点,并在界面上显示出来。

2、调用自己的曲线算法API,生成BezierCurve,以此线条为路径,生成管道。并显示。

3、调用自己的曲线算法API,生成NURBSCurve,缺省权重为1,degree为3,节点向量自行生成。以此线条为路径,生成管道。并显示。

4、调用 OCCT几何内核的BSpline API。以此线条为路径,生成管道。并显示。

5、调用 OCCT几何内核的BSpline  API  NUBRS曲线。以此线条为路径,生成管道。并显示。

void myCurveDemo(OccView *view)
{gp_Ax2 ax2;ax2.SetLocation(gp_Pnt(0, 0, 0));TopoDS_Edge circleEdge = BRepBuilderAPI_MakeEdge(gp_Circ(ax2, 0.1));const int pointCount=5;TColgp_HArray1OfPnt points(1, pointCount);points.SetValue(1, gp_Pnt(0.1, 0, 0));points.SetValue(2, gp_Pnt(1.1, 1, 1));points.SetValue(3, gp_Pnt(2.1, 2, 0));points.SetValue(4, gp_Pnt(3.1, 1, -1));points.SetValue(5, gp_Pnt(5.1, 1, -3));// points.SetValue(6, gp_Pnt(5.1, 4, 5));// points.SetValue(7, gp_Pnt(6.1, 5, -3));// points.SetValue(8, gp_Pnt(8.1, 2, -5));//显示控制点for(int i=1;i<=pointCount;i++){auto p=points.Value(i);showPoint(view,p,QString::number(i).toStdString().c_str(),false);}//调用自己的曲线算法API,生成BezierCurveauto curve=stone::CurveUtil::CreateBezierCurve(points);if(curve.IsDone()){Handle(AIS_ColoredShape) ais = new AIS_ColoredShape(curve.Wire());view->Display(ais);}
//调用自己的曲线算法API,生成NURBSCurve,缺省权重为1,degree为3,节点向量自行生成curve=stone::CurveUtil::CreateNURBSCurve(points);if(curve.IsDone()){auto wire=curve.Wire();Handle(AIS_ColoredShape) ais = new AIS_ColoredShape(wire);ais->SetColor(Quantity_NOC_MAROON);view->Display(ais);{//扫掠TopoDS_Shape pipe=BRepOffsetAPI_MakePipe(wire,circleEdge);Handle(AIS_Shape) aisPipe = new AIS_Shape(pipe);aisPipe->SetColor(Quantity_NOC_MAROON);view->Display(aisPipe);}}
//调用 OCCT几何内核的BSpline API{// Make a BSpline curve from the points arrayHandle(Geom_BSplineCurve) aBSplineCurve = GeomAPI_PointsToBSpline(points).Curve();// Make an edge between two point on the BSpline curve.gp_Pnt aPntOnCurve1, aPntOnCurve2;aBSplineCurve->D0(0.75 * aBSplineCurve->FirstParameter()+ 0.25 * aBSplineCurve->LastParameter(),aPntOnCurve1);aBSplineCurve->D0(0.25 * aBSplineCurve->FirstParameter()+ 0.75 * aBSplineCurve->LastParameter(),aPntOnCurve2);TopoDS_Edge anEdgeBSpline = BRepBuilderAPI_MakeEdge(aBSplineCurve);Handle(AIS_ColoredShape) anAisEdgeBSpline = new AIS_ColoredShape(anEdgeBSpline);anAisEdgeBSpline->SetColor(Quantity_Color(Quantity_NOC_MAGENTA));view->Display(anAisEdgeBSpline);{//扫掠auto wire=BRepBuilderAPI_MakeWire(anEdgeBSpline).Wire();TopoDS_Shape pipe=BRepOffsetAPI_MakePipe(wire,circleEdge);Handle(AIS_Shape) aisPipe = new AIS_Shape(pipe);aisPipe->SetColor(Quantity_NOC_MAGENTA);view->Display(aisPipe);}}//调用 OCCT几何内核的BSpline  API  NUBRS曲线{/// 均匀B样条,节点向量中的节点值成等差排布/// 均匀B样条的基函数呈周期性,即所有的基函数有相同的形状/// 每个后续基函数仅仅市前面基函数在新位置上的重复Standard_Integer degree(2);Standard_Integer KNum = pointCount + degree + 1;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)mults.SetValue(i+1, 1);Handle(Geom_BSplineCurve) curve = new Geom_BSplineCurve(points, knots, mults, degree);TopoDS_Edge ed1 = BRepBuilderAPI_MakeEdge(curve);TopoDS_Wire wr1 = BRepBuilderAPI_MakeWire(ed1);Handle(AIS_ColoredShape) ais = new AIS_ColoredShape(wr1);ais->SetColor(Quantity_NOC_SALMON);view->Display(ais);}{/// 准均匀B样条,节点向量中的节点值也是等差排布,但是起点和终点都有k-1的重复度,其中ke为曲线次数。Standard_Integer degree(2);Standard_Integer KNum = pointCount-1;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);elsemults.SetValue(i+1, 1);Handle(Geom_BSplineCurve) curve = new Geom_BSplineCurve(points, knots, mults, degree);TopoDS_Edge ed1 = BRepBuilderAPI_MakeEdge(curve);TopoDS_Wire wr1 = BRepBuilderAPI_MakeWire(ed1);Handle(AIS_ColoredShape) ais = new AIS_ColoredShape(wr1);ais->SetColor(Quantity_NOC_SIENNA);view->Display(ais);//扫掠圆,BSpline路径 BRepOffsetAPI_MakePipe{{TopoDS_Shape pipe=BRepOffsetAPI_MakePipe(wr1,circleEdge);Handle(AIS_Shape) aisPipe = new AIS_Shape(pipe);aisPipe->SetColor(Quantity_NOC_BISQUE);view->Display(aisPipe);}}}
}

运行效果:

从运行效果上来看,扫掠生成的管道,与曲线形状非常一致。

绿色的管道(粗线)和自定义算法生成的Bezier曲线路径,如下图:

绿色的管道(粗线)和自定义算法生成的NURBS曲线路径,如下图:

绿色的管道(粗线)和OCCT几何内核的NURBS曲线路径,如下图:

以上三个图中,黄色+处,是控制点位置。黄色+的右下边的数字1,2,3,4,5是控制点的顺序号。

这篇关于几何内核开发-实现自己的NURBS曲线生成API的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089274

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

通过高德api查询所有店铺地址信息

通过高德api查询所有店铺地址电话信息 需求:通过高德api查询所有店铺地址信息需求分析具体实现1、申请高德appkey2、下载types city 字典值3、具体代码调用 需求:通过高德api查询所有店铺地址信息 需求分析 查询现有高德api发现现有接口关键字搜索API服务地址: https://developer.amap.com/api/webservice/gui

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

DDei在线设计器-API-DDeiSheet

DDeiSheet   DDeiSheet是代表一个页签,一个页签含有一个DDeiStage用于显示图形。   DDeiSheet实例包含了一个页签的所有数据,在获取后可以通过它访问其他内容。DDeiFile中的sheets属性记录了当前文件的页签列表。   一个DDeiFile实例至少包含一个DDeiSheet实例。   本篇最后提供的示例可以在DDei文档直接预览 属性 属性名说明数

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st