当前位置: 首页 > wzjs >正文

宣城网站推广网站编辑seo

宣城网站推广,网站编辑seo,经典网站设计作品,石家庄做网站的公司使用多段圆弧来拟合一个由离散点组成的曲线,并且保证切线连续。也就是说,生成的每一段圆弧之间在连接点处必须有一阶导数连续,也就是切线方向相同。 点集分割 确保每个段的终点是下一段的起点,相邻段共享连接点,避免连接点位于数…

使用多段圆弧来拟合一个由离散点组成的曲线,并且保证切线连续。也就是说,生成的每一段圆弧之间在连接点处必须有一阶导数连续,也就是切线方向相同。

点集分割

确保每个段的终点是下一段的起点,相邻段共享连接点,避免连接点位于数据点之间。

int totalPoints = envelopePoints.size();
int m = (totalPoints - 1) / numArcs; // 每段间隔数,点数为m+1for (int i = 0; i < numArcs; ++i) {int startIdx = i * m;int endIdx = (i == numArcs - 1) ? (totalPoints - 1) : (startIdx + m);std::vector<gp_Pnt> segmentPoints(envelopePoints.begin() + startIdx, envelopePoints.begin() + endIdx + 1);// 处理该段
}

圆弧拟合约束

问题描述

给定起点 $ S(S_x, S_y) $、终点 $E(E_x, E_y) $ 和起点处的切线方向 $ \mathbf{T}(t_x, t_y) $,求解经过 $ S $ 和 $ E $ 的圆弧,并保证在 $ S $ 处的切线方向为 $ \mathbf{T} $。

推导过程

1. 圆心位置约束

圆心 $ C(O_x, O_y) $ 必须位于 $ S $ 点处与切线方向 $ \mathbf{T} $ 垂直的直线上。设 $ \mathbf{N}(-t_y, t_x) $ 为 $ \mathbf{T} $ 的法线方向,则圆心可表示为:
C = S + s ⋅ N C = S + s \cdot \mathbf{N} C=S+sN
即:
O x = S x − s ⋅ t y O_x = S_x - s \cdot t_y Ox=Sxsty
O y = S y + s ⋅ t x O_y = S_y + s \cdot t_x Oy=Sy+stx
其中,$ s $ 是圆心到$ S $点沿法线方向的距离,正负号表示方向。

2. 圆心到终点的距离约束

圆心到终点 $ E $ 的距离必须等于到起点$ S $ 的距离:
( E x − O x ) 2 + ( E y − O y ) 2 = ( S x − O x ) 2 + ( S y − O y ) 2 \sqrt{(E_x - O_x)^2 + (E_y - O_y)^2} = \sqrt{(S_x - O_x)^2 + (S_y - O_y)^2} (ExOx)2+(EyOy)2 =(SxOx)2+(SyOy)2
平方后得到:
( E x − O x ) 2 + ( E y − O y ) 2 = ( S x − O x ) 2 + ( S y − O y ) 2 (E_x - O_x)^2 + (E_y - O_y)^2 = (S_x - O_x)^2 + (S_y - O_y)^2 (ExOx)2+(EyOy)2=(SxOx)2+(SyOy)2

3. 代入圆心表达式

将 $ O_x $ 和 $ O_y $ 代入上式:
( E x − ( S x − s ⋅ t y ) ) 2 + ( E y − ( S y + s ⋅ t x ) ) 2 = ( S x − ( S x − s ⋅ t y ) ) 2 + ( S y − ( S y + s ⋅ t x ) ) 2 (E_x - (S_x - s \cdot t_y))^2 + (E_y - (S_y + s \cdot t_x))^2 = (S_x - (S_x - s \cdot t_y))^2 + (S_y - (S_y + s \cdot t_x))^2 (Ex(Sxsty))2+(Ey(Sy+stx))2=(Sx(Sxsty))2+(Sy(Sy+stx))2
简化右边:
( s ⋅ t y ) 2 + ( s ⋅ t x ) 2 = s 2 ( t x 2 + t y 2 ) = s 2 (s \cdot t_y)^2 + (s \cdot t_x)^2 = s^2 (t_x^2 + t_y^2) = s^2 (sty)2+(stx)2=s2(tx2+ty2)=s2
左边展开:
( E x − S x + s ⋅ t y ) 2 + ( E y − S y − s ⋅ t x ) 2 (E_x - S_x + s \cdot t_y)^2 + (E_y - S_y - s \cdot t_x)^2 (ExSx+sty)2+(EySystx)2
= ( E x − S x ) 2 + 2 s ⋅ t y ( E x − S x ) + s 2 t y 2 + ( E y − S y ) 2 − 2 s ⋅ t x ( E y − S y ) + s 2 t x 2 = (E_x - S_x)^2 + 2s \cdot t_y (E_x - S_x) + s^2 t_y^2 + (E_y - S_y)^2 - 2s \cdot t_x (E_y - S_y) + s^2 t_x^2 =(ExSx)2+2sty(ExSx)+s2ty2+(EySy)22stx(EySy)+s2tx2
= ( E x − S x ) 2 + ( E y − S y ) 2 + s 2 ( t x 2 + t y 2 ) + 2 s [ t y ( E x − S x ) − t x ( E y − S y ) ] = (E_x - S_x)^2 + (E_y - S_y)^2 + s^2 (t_x^2 + t_y^2) + 2s [t_y (E_x - S_x) - t_x (E_y - S_y)] =(ExSx)2+(EySy)2+s2(tx2+ty2)+2s[ty(ExSx)tx(EySy)]
由于 $ t_x^2 + t_y^2 = 1 $,上式进一步简化为:
= ( E x − S x ) 2 + ( E y − S y ) 2 + s 2 + 2 s [ t y ( E x − S x ) − t x ( E y − S y ) ] = (E_x - S_x)^2 + (E_y - S_y)^2 + s^2 + 2s [t_y (E_x - S_x) - t_x (E_y - S_y)] =(ExSx)2+(EySy)2+s2+2s[ty(ExSx)tx(EySy)]

4. 建立方程求解 $ s $

将左边和右边代入距离约束方程:
( E x − S x ) 2 + ( E y − S y ) 2 + s 2 + 2 s [ t y ( E x − S x ) − t x ( E y − S y ) ] = s 2 (E_x - S_x)^2 + (E_y - S_y)^2 + s^2 + 2s [t_y (E_x - S_x) - t_x (E_y - S_y)] = s^2 (ExSx)2+(EySy)2+s2+2s[ty(ExSx)tx(EySy)]=s2
化简得到:
( E x − S x ) 2 + ( E y − S y ) 2 + 2 s [ t y ( E x − S x ) − t x ( E y − S y ) ] = 0 (E_x - S_x)^2 + (E_y - S_y)^2 + 2s [t_y (E_x - S_x) - t_x (E_y - S_y)] = 0 (ExSx)2+(EySy)2+2s[ty(ExSx)tx(EySy)]=0
解得:
s = ( E x − S x ) 2 + ( E y − S y ) 2 − 2 [ t y ( E x − S x ) − t x ( E y − S y ) ] s = \frac{(E_x - S_x)^2 + (E_y - S_y)^2}{-2 [t_y (E_x - S_x) - t_x (E_y - S_y)]} s=2[ty(ExSx)tx(EySy)](ExSx)2+(EySy)2

5. 计算圆心和半径

代入 $ s$ 的值,得到圆心坐标:
O x = S x − s ⋅ t y O_x = S_x - s \cdot t_y Ox=Sxsty
O y = S y + s ⋅ t x O_y = S_y + s \cdot t_x Oy=Sy+stx
半径为:
R = ∣ s ∣ R = |s| R=s

6. 终点切线方向

圆弧在终点 $E $ 处的切线方向由圆心到$ E$ 的径向向量的垂直方向确定。径向向量为:
R = ( E x − O x , E y − O y ) \mathbf{R} = (E_x - O_x, E_y - O_y) R=(ExOx,EyOy)
切线方向为:
T E = ( R y , − R x ) \mathbf{T}_E = (R_y, -R_x) TE=(Ry,Rx)
归一化后得到终点处的切线方向。

7. 代码实现

// 计算必须经过起点和终点的圆弧参数
double Sx = arc.start.X();
double Sy = arc.start.Y();
double Ex = arc.end.X();
double Ey = arc.end.Y();
double tx = arc.startTangent.X();
double ty = arc.startTangent.Y();double numerator = (Ex - Sx) * (Ex - Sx) + (Ey - Sy) * (Ey - Sy); // SE_length squared
double denominator = 2 * (ty * (Sx - Ex) - tx * (Sy - Ey));if (std::abs(denominator) < 1e-6) {// 处理直线段情况arc.center = gp_Pnt(0, 0, 0);arc.radius = 0;arc.endTangent = arc.startTangent;arcs.push_back(arc);currentTangent = arc.endTangent;continue;
}double s = numerator / denominator;
double Ox = Sx - s * ty;
double Oy = Sy + s * tx;
arc.center = gp_Pnt(Ox, Oy);
arc.radius = std::abs(s);

切线连续性处理

计算每段圆弧终点处的切线方向,并传递给下一段作为起点切线方向。

// 计算终点切线方向
gp_Vec radialVec(arc.center, arc.end);
if (radialVec.Magnitude() < 1e-6) {arc.endTangent = currentTangent; // 避免除零
} else {radialVec.Normalize();arc.endTangent = gp_Dir(radialVec.Y(), -radialVec.X(), 0);
}
currentTangent = arc.endTangent;

完整代码实现

#include <vector>
#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
#include <gp_Vec.hxx>
#include <cmath>struct ArcSegment {gp_Pnt start;gp_Dir startTangent;gp_Pnt end;gp_Dir endTangent;gp_Pnt center;double radius;
};std::vector<ArcSegment> fitArcsWithTangentContinuity(const std::vector<gp_Pnt>& envelopePoints, int numArcs) {std::vector<ArcSegment> arcs;if (envelopePoints.size() < 2 || numArcs < 1) return arcs;int totalPoints = envelopePoints.size();int m = (totalPoints - 1) / numArcs; // 每段间隔数,点数为m+1gp_Dir currentTangent;for (int i = 0; i < numArcs; ++i) {int startIdx = i * m;int endIdx = (i == numArcs - 1) ? (totalPoints - 1) : (startIdx + m);if (startIdx >= envelopePoints.size() || endIdx >= envelopePoints.size() || startIdx > endIdx) {break; // Invalid segment, skip}std::vector<gp_Pnt> segmentPoints(envelopePoints.begin() + startIdx, envelopePoints.begin() + endIdx + 1);if (segmentPoints.size() < 2) {continue; // Not enough points to define a segment}ArcSegment arc;arc.start = segmentPoints.front();arc.end = segmentPoints.back();// Determine start tangent directionif (i == 0) {// First segment: use direction from first two pointsgp_Vec initialVec(segmentPoints[0], segmentPoints[1]);if (initialVec.Magnitude() < 1e-6) {currentTangent = gp_Dir(1, 0, 0); // Default direction} else {initialVec.Normalize();currentTangent = gp_Dir(initialVec);}arc.startTangent = currentTangent;} else {arc.startTangent = currentTangent;}double tx = arc.startTangent.X();double ty = arc.startTangent.Y();// Calculate parameters for constrained circle passing through start and end pointsdouble Sx = arc.start.X();double Sy = arc.start.Y();double Ex = arc.end.X();double Ey = arc.end.Y();double numerator = (Ex - Sx) * (Ex - Sx) + (Ey - Sy) * (Ey - Ey);double denominator = 2 * (ty * (Sx - Ex) - tx * (Sy - Ey));if (std::abs(denominator) < 1e-6) {// Handle straight line case (infinite radius)arc.center = gp_Pnt(0, 0, 0); // Not meaningful for straight linearc.radius = 0;arc.endTangent = arc.startTangent;arcs.push_back(arc);currentTangent = arc.endTangent;continue;}double s = numerator / denominator;// Calculate circle parametersdouble Ox = Sx - s * ty;double Oy = Sy + s * tx;arc.center = gp_Pnt(Ox, Oy);arc.radius = std::abs(s);// Calculate end tangent directiongp_Vec radialVec(arc.center, arc.end);if (radialVec.Magnitude() < 1e-6) {arc.endTangent = currentTangent; // Avoid division by zero} else {radialVec.Normalize();arc.endTangent = gp_Dir(radialVec.Y(), -radialVec.X(), 0);}currentTangent = arc.endTangent;arcs.push_back(arc);}return arcs;
}

关键点说明

  1. **点集分割:**通过均匀分割确保相邻段共享连接点,避免位置不连续。
  2. **圆弧约束拟合:**使用几何约束直接计算必须经过起点和终点的圆弧,保证位置连续。
  3. **切线连续性:**通过传递切线方向确保每段圆弧在连接点处切线方向一致。
  4. **特殊情况处理:**当分母接近零时,处理为直线段,避免计算错误。

此方案在保证切线连续的同时,简化了计算逻辑,适用于大多数离散点拟合场景。

http://www.dtcms.com/wzjs/217383.html

相关文章:

  • 宁夏建设厅网站首页网络营销策略的定义
  • 公安网站服务平台搜索引擎营销的特点是
  • 成都p2p网站建设友链通
  • wordpress数据库配置商品标题优化
  • 程序员做电商网站的公司好吗站长统计app
  • 做违法网站的后果东营优化公司
  • 网站上传文件代码seo优化设计
  • 广州做网站哪个公司做得好一个新的app如何推广
  • 衡水提供网站制作公司电话谷歌官方app下载
  • 做网站投注代理犯罪吗百度广告投诉电话
  • 网站开发属于无形资产电子商务网站建设
  • 介绍个人网站的ppt怎么做百度信息流广告怎么投放
  • 网站搭建怎么收费交换友链平台
  • 化妆品营销型网站打开百度网页
  • 安装多个wordpress谷歌优化师
  • tp5做企业网站深圳网站优化公司
  • 汽车网站建设公司哪家好湖人排名最新
  • 做618购物网站的总结环球网最新消息疫情
  • 网站如何做关键词seo什么是优化师
  • 辽阳公司做网站网址导航哪个好
  • 做慕课的网站大连网站建设
  • 旅游网站的设计方案怎么做seo排名
  • 技术支持 郑州做网站seo优化顾问服务阿亮
  • 广州市 网站建设 有限公司seo是什么意思 seo是什么职位
  • 网站购买域名之后再怎么做专业营销策划团队
  • 刷题网站怎么做百度seo免费推广教程
  • 美术生十大最烂专业seo最强
  • crm微信管理系统seo关键词教程
  • 网络营销专员的就业前景深圳seo优化服务
  • 韩国flash网站百度云盘登录