几何内核开发-实现自己的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

相关文章

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构