C# 定积分求周长&面积原理 代码实现
前言:
前些日子,因为工作原因,接触到了求解曲线周长,真的是搞了很久,学生时代真的很简单,但是如今的我来说,忘记了....很多人跟我应该一样。
所以来巩固加强一下记忆。一开始的时候,求周长嘛,找公式呗,什么matlab呀,乱七八糟的,晕,最后找到了可能还不能满足项目的需求,因为可能计算量过大。(我就是这样子的,灵活性相对较低)
还有就是明明自己可以用代码实现,为什么非要插件,工具呐,这么不自信的?
所以,“一怒之下”,自己去看了一下定积分求周长的原理,自己还是用代码来实现吧。
(以下内容纯是个人这段时间的理解,如果有错误的,欢迎指正出来。)
首先需要说说两个概念,曲线和周长,因为我们要求他们嘛。
曲线:
这个世界,有曲线吗?我的回答是,没有。那...这...曲线是由无数个直接拼接而成。再准确的说无数个很短的曲线拼接而成。
(如果您彻底理解了这句话,后面就不用看了,基本就没了。)
面积:
与周长的概念类似,没有正方形,没有圆形。只有三角形,所有的图形都是三角形拼接而成。而两个三角形拼成长方形,而我们的面积是由无数个长方形,拼接而成。
(定积分原理的参考图)
源码实现:
double GetLength(float start,float end) { double sumLength = 0; float eachX = (end - start) / testCount; for (int i = 1; i < testCount;i++ ) { double curY =ArcFunction(start+eachX*i); double previousY = ArcFunction(start+eachX*(i-1)); //根据c²=a²+b² double curLength = Math.Sqrt(Math.Pow(eachX, 2) + Math.Pow(curY - previousY, 2)); sumLength += curLength; } return sumLength; }
解释:
testCount,即自定义的测试数量,可以理解为精细度,值越大,计算量越大,数据越准确,这个可看你项目需求精细度,通过该变量
可在实现最少的计算量情况,实现你要的效果。
eachX,就是你的曲线被分成N份,每份的长度。
curY,当前点的y轴分量
previousY,上一个点的y轴分量,
curLength,即如图
(剩余的部分,代码里面含解释,个人喜欢放在源码里面,原生的,纯24k原创)
int testCount = 1000; //所谓的测试细致度吧,可动态调控,你自己掌握。 /// <summary> /// 通过已知周长,获取x轴的分量 /// </summary> /// <param name="length"></param> /// <returns></returns> double GetRateXByLength(double length) { float eachX = 1.0f; for (int i = 1; i < testCount; i++) { double curY = ArcFunction(eachX * i); double previousY = ArcFunction(eachX * (i - 1)); double curLength = Math.Sqrt(Math.Pow(eachX, 2) + Math.Pow(curY - previousY, 2)); length -= curLength; if(length<=0) { return i * eachX; } } return testCount * eachX; } /// <summary> /// start到end范围内的面积 /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> double GetArea(float start,float end) { double sumAera = 0; float eachX = (end - start) / testCount; for (int i = 1; i < testCount; i++) { double curY = ArcFunction(start + eachX * i); //面积 = 长*宽 double curAera = curY * eachX; sumAera += curAera; } return sumAera; } /// <summary> /// 通过已知面积,获取x轴分量 /// </summary> /// <param name="aera"></param> /// <returns></returns> double GetRateXByAera(double aera) { float eachX = 1.0f; for (int i = 1; i < testCount; i++) { double curY = ArcFunction(eachX * i); double curAera = curY * eachX; aera -= curAera; if(aera<=0) { return i * eachX; } } return testCount*eachX; } /// <summary> /// 通过x分量,得出y的值。(好像意义不大,但是好像可能有些人不是很理解,写给某些人看的,一目了然) /// </summary> /// <param name="x"></param> /// <returns></returns> double GetYByX(float x) { return ArcFunction(x); } /// <summary> /// 核心控制函数。 /// </summary> /// <param name="x"></param> /// <returns></returns> double ArcFunction(float x) { return Math.Pow(x, 2); //这边我用幂函数来测试。各位爷可以换其他函数啊。 //注:如果对曲线灵活性要求很高,推荐使用贝塞尔曲线。 //详情可参考: }
补充:这边,我对贝塞尔曲线做一下补充吧。因为我因为什么幂函数,指数函数遇到的肯,因为这些函数毕竟还不是那么灵活,都具有一定“规律”。
贝塞尔曲线的灵活,受6个参数控制,三个点嘛。(二维空间)
详情可参考这篇:http://www.sohu.com/a/118656687_466876
======================================= 2018年9月3日补充================================================================
可以使用第三方插件:开源Math.Net进行数值积分。
参考:https://www.cnblogs.com/asxinyu/p/4301017.html
public static double OnClosedInterval(Func<double, double> f, double intervalBegin, double intervalEnd);
void Start () { var result = Integrate.OnClosedInterval(TestFunc, 0, 24); Debug.Log(result); } double TestFunc(double x) { return x * x; }
但是上述的result为面积,也是dy。
再根据定积分求弧长公式:
即:弧长 = √(1+result²)
===================================================================================================================
- Java NIO原理图文分析及代码实现<转>
- 编译原理-词法分析04-NFA & 代码实现
- BP神经网络原理推到&代码实现
- 『HTML5实现人工智能』小游戏《井字棋》发布,据说IQ上200才能赢【算法&代码讲解+资源打包下载】
- java NIO原理 图文分析及代码实现
- JSONP原理及代码简单实现
- 【清楚理解后台利用ireport到处报表的原理】ireport制作jasperreport报表详细过程(包括jsp端代码实现)
- 堆排序原理详解和Java实现代码
- 用FPGA实现8'bitSRAM读写控制的Verilog代码
- PHP实现阶乘的原理与代码分析
- android Setting中隐藏项实现原理与代码
- 仿网易nec首页动画效果(实现原理+代码)
- Java NIO原理图文分析及代码实现
- GlusterFS之内存池(mem-pool)实现原理及代码详解
- Android中悬浮窗口的实现原理和示例代码
- java_security之base64原理解析以及三种代码的实现方式
- 导向滤波小结:从导向滤波(guided filter)到快速导向滤波(fast guide filter)的原理,应用及opencv实现代码
- 五行代码实现 炫动滑动 卡片层叠布局,仿探探、人人影视订阅界面 简单&优雅