基于C/C++的椭圆等间距离散方法

参考文档与博客:
https://blog.csdn.net/baidu_38621657/article/details/87907829

https://blog.csdn.net/baidu_38621657/article/details/87907829

理论部分

由于椭圆弧长积分的解析解不存在,用数值分析方法近似求解。
下面以第一象限椭圆弧为例说明一种近似求解方法

(1)首先圆是椭圆的特殊形式,长短轴长相等,对于圆心角为θ的圆弧长为Rθ,当圆心角足够小时可以认为tanθ≈θ,弧长可以认为L≈Rtanθ≈R*θ,其中R为圆心到微段弧上点的距离,这个近似简化对于椭圆弧同样有效。

(2)对于椭圆,其参数方程为

x=acosθ
y=b
sinθ
这里a,b分别对应椭圆外切圆与内接圆的半径(与下图对应)。

在此约定θ为逆时针方向与X轴之间的夹角

图中点A对应的参数角θ如图所示,α为其对应的扫略角,θ和α之间可以相互转换。

圆心O到点P之间距离|OP|=sqrt(x2 + y2) =sqrt[(acosθ)2+(bsinθ)2)],可得θ与|OP|的关系。

(3)当a=50,b=30时,得|OP|在不同θ时值
以θ为x轴,|OP|为y轴时,曲线图近似为折线段如图中绿色线curve1

绿色线curve1与x轴之间面积即为θ为0 ~ π/2时对应椭圆弧长,此时可将绿色线curve1近似为图中白色直线段curve2(为了更精确也可简化为连续折线段),即白色线curve2与x轴之间面积A=(a+b)*(π/4)(梯形面积公式),近似为θ为0~PI/2时对应椭圆弧长。

此时将椭圆弧按长度等分即可转化为将面积A按θ等分问题
curve2斜率为k=(b-a)/(π/2),方程为y=(2b-2a)/π*x+a,其与x轴之间面积积分为

∫ydx=∫[(2b-2a)/πx+a]dx=(b-a)/πx2+a*x+c,其中c为常数项,

令f(x)=(b-a)/πx2+ax,若将椭圆弧等分位n份,每份面积为A/n
f(θ1)-f(0)=f(θ1)=A/n,
f(θ2)-f(θ1)=A/n,

f(θn)-f(θn-1)=A/n

构造方程l来求解每一个点所对应的旋转角度:
((a-b)/π)x2+bx-4Aj/n
这里的j值的范围从1到离散坐标总数。

其次椭圆的周长计算参考:
https://www.mathsisfun.com/geometry/ellipse-perimeter.html

C++代码实现

求解各个点所对应的θ(求解方程)

root roots(double r1, double r2,int j, int N)
{root solu;double a, b, c;a = (r1 - r2) / pi;b = r2;double A = (r1 + r2) * pi / 4;c = -4 * A / N * (j+1);double discriminant = b * b - 4 * a * c;if (discriminant > 0) {solu.m_x1 = (-b + sqrt(discriminant)) / (2 * a);solu.m_x2 = (-b - sqrt(discriminant)) / (2 * a);}else if (discriminant == 0) {//cout << "Roots are real and same." << endl;solu.m_x1 = -b / (2 * a);cout << "x1 = x2 =" << solu.m_x1 << endl;}else {//realPart = -b / (2 * a);//imaginaryPart = sqrt(-discriminant) / (2 * a);cout << "Roots are complex and different." << endl;//cout << "x1 = " << realPart << "+" << imaginaryPart << "i" << endl;//cout << "x2 = " << realPart << "-" << imaginaryPart << "i" << endl;}return solu;
}

椭圆离散函数:

void discretizeEllipse(//椭圆离散化为多边形double x, double y, double r1, double r2, double alpha, double L)//x,y为中心点坐标,r1长轴长度,r2短轴长度,alpha椭圆旋转角度,L离散的线段长度
{double P = 2 * pi * sqrt((r1*r1 + r2*r2) / 2);double N = P / L; //计算需要划分的段数N = 4 * round((double)N / 4);//将段数转换为4的倍数'if (N == 0)N = 4;for (int j = 0; j < N / 4; j++){root rts;rts = roots(r1,r2,j,N);root_out.push_back(rts.m_x1);}for (int k = 0; k < N; k++){if (k < N / 4){p_out.push_back(root_out[k]);}else if ((k >= N / 4) && (k < N / 2 - 1)){p_out.push_back(pi - root_out[N / 2 - k - 2]);}else if (k == N / 2 - 1){p_out.push_back(3.1415);}else if ((k > N / 2 - 1) && k < N * 3 / 4){p_out.push_back(pi + root_out[k - (N / 2)]);}else if (k >= N * 3 / 4 && k < N - 1){p_out.push_back(2 * pi - root_out[N - k - 2]);}else{p_out.push_back(2 * pi);}}for (int m = 0; m < N; m++){double x1 = r1 * cos(p_out[m]);double y1 = r2 * sin(p_out[m]);double x2 = x1 * cos(alpha) - y1 * sin(alpha);double y2 = x1 * sin(alpha) + y1 * cos(alpha);x2 = x2 + x;y2 = y2 + y;vec_out.push_back(x2);vec_out.push_back(y2);}
}

完整代码

#include <algorithm>
#include <graphics.h>
#include<vector>
#include <fstream>
#include<math.h>
#include<iostream>
#define pi 3.1415926using namespace std;
class root
{
public:  //访问权限  公共的权限//属性double m_x1;//根double m_x2;
};
vector <double> root_out;//存储根
vector <double> p_out; //存储整合后的根
vector <double> vec_out;//坐标输出root roots(double r1, double r2,int j, int N)
{root solu;double a, b, c;a = (r1 - r2) / pi;b = r2;double A = (r1 + r2) * pi / 4;c = -4 * A / N * (j+1);double discriminant = b * b - 4 * a * c;if (discriminant > 0) {solu.m_x1 = (-b + sqrt(discriminant)) / (2 * a);solu.m_x2 = (-b - sqrt(discriminant)) / (2 * a);}else if (discriminant == 0) {//cout << "Roots are real and same." << endl;solu.m_x1 = -b / (2 * a);cout << "x1 = x2 =" << solu.m_x1 << endl;}else {//realPart = -b / (2 * a);//imaginaryPart = sqrt(-discriminant) / (2 * a);cout << "Roots are complex and different." << endl;//cout << "x1 = " << realPart << "+" << imaginaryPart << "i" << endl;//cout << "x2 = " << realPart << "-" << imaginaryPart << "i" << endl;}return solu;
}void discretizeEllipse(//椭圆离散化为多边形double x, double y, double r1, double r2, double alpha, double L)//x,y为中心点坐标,r1长轴长度,r2短轴长度,alpha椭圆旋转角度,L离散的线段长度
{double P = 2 * pi * sqrt((r1*r1 + r2*r2) / 2);//float P = 2 * pi * sqrtf((r1^2 + r2 ^ 2) / 2);double N = P / L;   N = 4 * round((double)N / 4);if (N == 0)N = 4;for (int j = 0; j < N / 4; j++){root rts;rts = roots(r1,r2,j,N);root_out.push_back(rts.m_x1);}for (int k = 0; k < N; k++){if (k < N / 4){p_out.push_back(root_out[k]);}else if ((k >= N / 4) && (k < N / 2 - 1)){p_out.push_back(pi - root_out[N / 2 - k - 2]);}else if (k == N / 2 - 1){p_out.push_back(3.1415);}else if ((k > N / 2 - 1) && k < N * 3 / 4){p_out.push_back(pi + root_out[k - (N / 2)]);}else if (k >= N * 3 / 4 && k < N - 1){p_out.push_back(2 * pi - root_out[N - k - 2]);}else{p_out.push_back(2 * pi);}}for (int m = 0; m < N; m++){double x1 = r1 * cos(p_out[m]);double y1 = r2 * sin(p_out[m]);double x2 = x1 * cos(alpha) - y1 * sin(alpha);double y2 = x1 * sin(alpha) + y1 * cos(alpha);x2 = x2 + x;y2 = y2 + y;vec_out.push_back(x2);vec_out.push_back(y2);}
//输出至文件ofstream ofs;ofs.open("test1.txt", ios::out);ofs << vec_out.size() << endl;for (int i = 0; i < vec_out.size(); i++){ofs << vec_out[i] << endl;}ofs.close();
}
void main()
{discretizeEllipse(0,0,50,40,0,20);system("pause");
}

matlab绘制离散结果

基于C/C++的椭圆等间距离散方法相关推荐

  1. 基于几何距离的椭圆拟合

    问题 给定离散点集Xi=(xi,yi)X_i=(x_i,y_i)Xi​=(xi​,yi​),我们希望找到最好的椭圆去拟合这些离散点. 方法 通常我们使用最小二乘法求解如下的最优化问题: Min∑i=1 ...

  2. 主要内容: 本文提出了一种基于(ppo)的微电网最优调度方法。 该方法采用强化学习(RL)来学习调度策略,并积累相应的调度知识。 同时,引入ppo模型,将微电网调度策略动作从离散动作空间扩展到连续动作

    MATLAB代码:微电网 强化学习 关键词:微电网 强化学习 RL Reinforcement Learning 参考文档:<Optimal Scheduling of Microgrid Ba ...

  3. 光子筛matlab,一种振幅调制器件产生椭圆涡旋光的方法与流程

    本发明涉及衍射光学领域,具体涉及一种振幅型仿螺旋光子筛. 背景技术: 所谓涡旋光束即具有连续螺旋相位的光束,换句话说,光束的波阵面既不是平面,也不是球面,而是像旋涡状,具有奇异性.涡旋光束具有柱对称的 ...

  4. matlab计算潮差程序,一种基于FVCOM模型的可视化潮汐潮流预报方法与流程

    本发明涉及潮汐预报技术领域,特别是涉及一种基于FVCOM模型的可视化潮汐潮流预报方法. 背景技术: 潮汐预报对一定海区在未来一定时间内的潮汐涨落情况进行的推算和预报.预报内容包括逐日的高潮和低潮高度及 ...

  5. 基于“分布 —— 多分布” 的点云配准方法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:iceytan | 来源:知乎 https://zhuanlan.zhihu.com/p/135 ...

  6. 一种基于说话人识别和数字语音识别的身份认证方法与流程

    本发明属于语音处理技术领域,具体涉及到对数字语音序列进行说话人识别和语音识别,确定说话人身份的身份认证方法. 背景技术: 说话人识别也称为声纹识别,可以从说话人发出的声音中提取其个性特征,从而识别出当 ...

  7. 一种基于敏感度可调的语音情感识别方法及系统

    一种基于敏感度可调的语音情感识别方法及系统 技术领域 本发明属于语音识别领域,尤其涉及一种基于敏感度可调的语音情感识别方法及系统. 背景技术 情感是人类交流手段的一种常见的表达方式,在人机交互中起着重 ...

  8. 基于多任务学习的快件送达时间预测方法

    1.文章信息 文章题目为<基于多任务学习的快件送达时间预测方法>,发表在计算机工程期刊上的一篇有关多任务学习预测的文章. 2.摘要 快件送达时间预测是物流领域中一项至关重要的服务.准确地预 ...

  9. 基于时频域统计特征提取的自然环境声音识别方法

    Description 基于时频域统计特征提取的自然环境声音识别方法 技术领域 [0001] 本发明属于声音信号识别技术领域,尤其涉及一种基于时频域统计特征提取的自 然环境声音识别方法. 背景技术 [ ...

最新文章

  1. Docker镜像优化
  2. 抛弃windows用linux来工作吧
  3. VS2010静态编译
  4. vivado环境下实现比较器
  5. 前端学习(3333):ant design介绍按钮类型
  6. 【Python CheckiO 题解】Long Repeat
  7. js字符串replace替换多个_汇总几大python常见字符串处理函数与用法(建议收藏)...
  8. nginx部署两个php虚拟主机,nginx服务器,fastcgi模式,添加虚拟主机(多站点)配置...
  9. 【Hadoop】同步集群时间
  10. Python字符串的截取|Python练习题
  11. 钝化 会钝化 订单审批流程 码一会er
  12. power builder的安装和使用
  13. 【可靠性测试】之容错性测试---测试检查点罗列
  14. c语言趣味菜单实验报告,DSP实验报告+心得体会
  15. 2022机器学习好网站大收藏
  16. html光标效果,css鼠标光标样式
  17. 适用于Android手机的汉信码识别SDK
  18. linux module 目录,linux module工具安装与使用
  19. maven中无法下载ojdbc
  20. Android Vendor Test Suite (VTS) 的概念、作用及测试方法

热门文章

  1. NB-IoT技术是未来发展趋势,作为一个物联网创业者有什么机会?
  2. 找不到dlopen failed: library /data/data/com.example.gpstest1/lib/libgnustl_shared.so not found
  3. git补充子模块,git下载文件夹是空的
  4. pytorch项目怎么跑?
  5. DyGLIP:跨摄像头多目标跟踪的动态图模型
  6. 你知道单片机的工作条件吗?51单片机和52单片机有何区别?
  7. Redis消息队列 | 黑马点评
  8. QQ小游戏、微信小游戏获取ip地址,并通过ip得到所在地区
  9. boss直聘Android找工作界面,仿Boss直聘我的界面滑动效果
  10. 项目实战典型案例11——生产环境重大事故