精华内容
下载资源
问答
  • 判断曲线是否连续
    千次阅读
    2013-03-16 13:52:51
    #include<stdio.h>
    #include<stdlib.h>
    
    bool IsContinuous1(int *arr,int N)
    {/*整数数列,元素取值为0...65535中任意一个不重复的数,0可以出现多次
    	1、元素值可以乱序。
    	2、0可以匹配任何数值。
    	3、0可以多次出现。
    	4、全0算连续、只有一个非0也算连续。
     */
    	int min = -1,max = -1;
    
    	for(int i = 0;i < N; ++i)
    	{
    		if(arr[i] != 0)
    		{
    			if( min > arr[i] || -1 == min)
    				min = arr[i];
    			if( max < arr[i] || -1 == max)
    				max = arr[i];
    		}
    	}
    
    	if(max - min > N - 1)
    		return false;
    	else
    		return true;
    }
    
    int cmp(const void *a,const void *b)
    {
    	return *(int *)a - *(int *)b;
    }
    
    
    bool IsContinuous2(int *arr,int N)
    {//其他条件同上,但是允许有重复值
    
    	qsort(arr,N,sizeof(int),cmp);
    	int zeronum = 0;        //0的数目
    	int i = 0;
    	int gap = 0;            //数组arr中最大元素和最小元素只差
    	while( arr[i++] == 0)
    		zeronum++;
    	i--;
    	gap = arr[N - 1] - arr[i];
    	if(gap > N -1 && gap > zeronum)
    		return false;
    	else
    		return true;
    }
    
    
    
    
    int main()
    {
    	int array[] = {1,3,2,5,7,0,8,2,3,5,7,7,7,7,7,5};
    	int len = sizeof(array) / sizeof(array[0]);
    
    	if(IsContinuous2(array,len))
    		printf("连续\n");
    	else
    		printf("不连续\n");
    
    	return 0;
    }

    更多相关内容
  • 主要介绍了C#画笔Pen绘制光滑模式曲线的方法,涉及C#图形绘制画笔Pen相关属性的设置技巧,需要的朋友可以参考下
  • Qt Creator 多轴曲线

    2020-10-17 11:30:01
    QT上位机例程,使用QT5进行编写,经过实际的测试完全可以用,用Qt Creator软件创建具有两个垂直轴的曲线图表。内有使用说明。
  • 包络理论中通常采用速度与法矢正交的条件来判断曲线族上的点是否为特征点,它要求曲线至少C1连续,而对于C0连续的曲线则无能为力。在此背景下,提出了扩展的包络条件来适应C0连续的曲线包络的计算,并证明了在C1连续...
  • 1、西门子S7_1500实现判断当前位置与目标位置的关系,基于sinxsinx函数自动生成S型曲线轮廓,并使用插补对轮廓进行密集插值,保证曲线的平滑度。 2、由于 SinxSinx 曲线具有的一阶二阶连续性,加速度和加加速度都...
  • 一个简单的例子从最简单的情况出发,连续可微的封闭曲线为边界的,最简单例子是”圆”. ——“什么?你忽悠我?!” 为了不至于激起不满,我临时决定把这个简单的例子更改为椭圆。当然,如果椭圆的长短轴跟直角坐标...

    先把标题放在这里,内容我慢慢准备,一点点添加1.

    一个简单的例子

    从最简单的情况出发,连续可微的封闭曲线为边界的,最简单例子是”圆”.
    ——“什么?你忽悠我?!”
    为了不至于激起不满,我临时决定把这个简单的例子更改为椭圆。当然,如果椭圆的长短轴跟直角坐标系的坐标轴平行,其实也还简单,所以让它再旋转一个角度 θ 。所以我选择了如下参数方程的椭圆:

    {x=y=5costcosθ3sintsinθ3cosθsint+5costsinθ

    为了把曲线画出来, 让 θ=30o , 从而其参数方程变为:

    x=y=12(53cost3sint)12(5cost+33sint)

    ParametricPlot[RotationTransform[Pi/6][curve], {t, 0, 2 Pi}] /.  Line[x_] :> {Red, Line[x]}

    旋转了30°的椭圆

    要判断任给点 P=(x0,y0) 是不是在图中的浅蓝色区域:
    填充了的旋转30°的椭圆

    不知道常用的都是什么办法? 2.
    .
    至少对圆的情形,判断的方法是到圆心的距离跟圆的半径作比较. 但是椭圆不同了,而且旋转了 θ 角,让自然参数 t 也不直接对应于P点的方位了,只是稍微增加了一点点麻烦而已,仍然可以找出椭圆上的边界点,然后对比到椭圆圆心的距离. 这个方法太原始了,而且不易推广,显然不是我想说的.

    看看math.stackexchange.com上人家怎么说吧.如何确定任一点是否在二次曲线内,我当然不是为了转一个链接而卖关子. 链接里的方法主要还是对方程为隐函数 g(x,y)=Ax2+Bxy+Cy2+Dx+Ey+F=0 形式的二次曲线,利用其二次型.但仅适用于二次曲线.

    大部分情况下,参数方程更方便,而且两种形式之间互换本来也挺麻烦. 这里介绍基于椭圆的参数方程时,如何判断; 同时,把这个例子里的概念推广到更一般的高于二次的 C 曲线,以及凸的和凹的多边形.

    这个概念就是拓扑学中的winding number卷绕数3.

    很容易把任意曲线的参数方程:

    {x=y=x(t)y(t)

    改写成极坐标形式:
    ρ=θ=x(t)2+y(t)2arctan(y(t)x(t)) ,,x(t)=0

    求导数之后(参考维基上的内容winding number卷绕数):

    dθ=x(t)y(t)y(t)x(t)x(t)2+y(t)2dt

    曲线 x(t)y(t) 在某点 (x0,y0) 卷绕数定义为:

    w(x0,y0)=12πt1t0(x(t)x0)y(t)(y(t)y0)x(t)(x(t)x0)2+(y(t)y0)2dt

    对于前面提到的椭圆: t0=0,t1=2π ,**当 w(x0,y0) 为0时,点在椭圆外,为非0整数时在其内。

    这个结论使得用数值积分计算结果作为判据非常合适,因为它对积分的数值计算有很大的允许误差; 从维基还是某本书上提到,winding number在量子力学里面又是一种”量子数”(稍后核实出处)。

    Mathematica代码做个试验:

    curve={5Cos[t],3Sin[t]};  (*标准椭圆定义*)
    {x[t],y[t]}=RotationTransform[Pi/6]@curve; (*旋转30°的参数形式*)
    innerQ[{x0_,y0_}]:=Round[NIntegrate[((x[t]-x0)D[y[t],t]-(y[t]-y0)D[x[t],t])/((x[t]-x0)^2+(y[t]-y0)^2),{t,0,2Pi}]/2/Pi]!=0 (*以卷绕数为判据的函数的定义*)
    innerQ /@ {{3, 5}, {3, 2}, {0, 0}, {-4, 1}} (*测试几个点*)
    {False, True, True, False}(*输出结果*)

    太丑了! 换个表现方式!!

    ClearAll["Global`*"]
    curve={5Cos[t],3Sin[t]};
    new=RotationTransform[Pi/6]@curve;
    x[t_]:=new[[1]]
    y[t_]:=new[[2]]
    innerQ[{x0_,y0_}]:=Round[NIntegrate[((x[t]-x0)D[y[t],t]-(y[t]-y0)D[x[t],t])/((x[t]-x0)^2+(y[t]-y0)^2),{t,0,2Pi},AccuracyGoal->6]/2/Pi]!=0
    hc=ParametricPlot[u*RotationTransform[Pi/6]@curve,{t,0,2Pi},{u,0,1},PlotRange->{{-5,5},{-4.5,4.5}},PlotPoints->30,MeshFunctions->{#4&},Mesh->{{1.1}},MeshShading->{Yellow,Yellow}]/.Line[_]:>Sequence[];
    SeedRandom[5]
    (points=RandomReal[{-4,4},{10,2}]);
    txt=Text[Style[#,Red,20],points[[#]],{1,0}]&/@Range[Length@points];
    v=innerQ/@points;
    Join[points,ConstantArray["->",{10,1}],Transpose@{Range[10]},Transpose@{v},2]//MatrixForm
    Show[hc,Graphics[{Blue,AbsolutePointSize[6],Point[#]&/@(1.15points)}],Epilog->{Red,txt},Frame->True,ImageSize->Large]

    输出结果是这样滴:

    编号点的坐标是否在曲线封闭区域之内
    1(-3.99368, -3.47985)不在
    2(3.91644, 3.75014)不在
    3(-2.39307, 2.55617)不在
    4(-3.28189, 3.76561)不在
    5(-2.16072, 0.90002)
    6(-3.22547, 0.39084)
    7(-2.93962, -2.14134)
    8( 2.20908, 0.40759 )
    9(-3.53048, 3.68482)不在
    10(-3.21401, -3.72518)不在

    ……………………………………………………………………………………………………………………………..
    这里写图片描述

    卷绕数的几何意义

    这个部分希望能够增加一点直观生动的内容。

    一个深入点的例子

    前面的例子其实不能算简单,我开始后悔没有用”圆“了。

    如果说圆和椭圆的情况,都还可以通过测量到”形心距离”之类的方法——即便有些小周折,这让基于winding number卷绕数的方法还是有些不太自在的——”深入点的例子“必须给常规的潜在竞争关系的方法制造足够的麻烦,或者至少要让心目中想要突出的、中意的方法干得更加漂亮!

    下面这个例子,一方面仍然保持图形以及参数方程本身在视觉上或表面看上去的足够简单,同时希望让那些初级的方法更加步履维艰,否则我写了这么多不是瞎忙活吗。这条曲线的参数方程是:

    {x(t)=y(t)=9sin2t+5sin3t9cos2t5cos3t

    把它画出来是这样的,看上去是不是有些似曾相识?
    这里写图片描述
    在用凹多边形表述发现代码太长之后,我想尝试用曲线近似表达一颗五角星,结果就找到了它。它的边上的肌肤的线条都是 C 光滑的,不像凹多边形那样有棱有角;但是形状有非常近似;所有的边界都可以用一个方程表达,看上去似乎有压缩代码的潜力。如果可以简洁高效地判断出内点外点,只须再作如下填充不就是五角星了吗:
    这里写图片描述
    代码悄悄地:

    Grid@{{ParametricPlot[u {9 Sin[2 t]+5 Sin[3 t],9 Cos[2 t]-5 Cos[3 t]},{t,0,2 Pi},{u,0,1},MeshFunctions->{(*Sqrt@(#1^2+#2^2)*)#4&},Mesh->{{1}},PlotPoints->30,MeshStyle->Red,MeshShading->{{Cyan,LightGreen}},ImageSize->Large]/.Line[x_]:>{Red,Line[x]},ParametricPlot[u {9 Sin[2 t]+5 Sin[3 t],9 Cos[2 t]-5 Cos[3 t]},{t,0,2 Pi},{u,0,1},MeshFunctions->{(*Sqrt@(#1^2+#2^2)*)#4&},Mesh->{{1}},PlotPoints->30,MeshStyle->Red,MeshShading->{{Red,Red}},ImageSize->Large,Axes->False]/.Line[x_]:>{Red,Line[x]}}}

    郁闷的是,对它进行判断的方法,跟椭圆的时候没有区别。所以,这部分就不讲了。连个偷着乐的表情都不能发,MarkDown太死板、不灵活。不过算法似乎可以趁机把MarkDown的流程图练习一下, 等着吧。

    此外,对于这个例子为何比椭圆情况更进一步没有解释。
    对winding number的解释,也缺乏维基那样生动的动态演示.
    虽然不是必要的,作为练习还是可以慢慢加上来的.

    向多边形的推广

    惊艳的其中一部分在这里。 拓扑的确不一样。

    卷绕数在五角星绘制中的应用实例

    本来问题就是从绘制五星红旗开始的。为了压缩代码,希望找到一个新的判断内外点的算法。现在不论成功与否,贴代码吧。

    我只把高级语言当作表达某些意思的工具,但是从来没有去研究关于这类工具的特殊的形式和技巧,无从着手,也不是特别感兴趣。所以,算法在此,进一步压缩只能翘首等别人了。

    // NOTE: compile with g++ filename.cpp -std=c++11
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <vector>
    //#include <functional>
    #define DIM1 600
    #define DIM2 400
    #define DM1 (DIM1-1)
    #define DM2 (DIM2-1)
    #define _sq(x) ((x)*(x)) // square
    #define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
    #define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
    
    #define pi 3.14159
    #define eps 2.02e-16
    double arct(double x,double y){//可改写为宏放Rd函数中
        return abs(x)>eps?(x>eps?atan(y/x):(y>0?atan(y/x)+pi:atan(y/x)-pi)):(y>0?pi/2:-pi/2);
    }
    
    bool inQ(int i,int j,int* px){//改为lambda表达式放GR/BL中
        double art[5],aro[5];
        for(int k=0;k<5;k++){
            art[k]=arct((double)(px[k]-i),(double)(px[k+5]-j));//
        }
        double total=0.;
        for(int k=0;k<5;k++){
        aro[k]=art[(k+1)%5]-art[k];
            while(aro[k]<-pi) aro[k]+=pi;
            while(aro[k]>pi) aro[k]-=pi;
        total+=aro[k];
        }
        return abs(total)>0.5;
        };//即使修改了也只能作有限压缩,不能达到420字符水平
    
    unsigned char GR(int,int);
    unsigned char BL(int,int);
    
    unsigned char RD(int i,int j){
    // YOUR CODE HERE
        return 255;
    }
    unsigned char GR(int i,int j){
    // YOUR CODE HERE
                int p1[10]={100, 135, 43, 157, 65, 40, 149, 81, 81, 149},
            p2[10]={184, 220, 183, 207, 205, 168, 181, 191, 161, 199},
            p3[10]={183, 208, 204, 185, 220, 50, 22, 59, 27, 42},
            p4[10]={221, 259, 229, 239, 252, 135, 133, 157, 120, 156},
            p5[10]={220, 254, 237, 231, 258,83, 66, 100, 62, 89};
        return inQ(i,j,p1)||inQ(i,j,p2)||inQ(i,j,p3)||inQ(i,j,p4)||inQ(i,j,p5)?255:0;
    }
    unsigned char BL(int i,int j){
    // YOUR CODE HERE
        return 0;
    }
    
    void pixel_write(int,int);
    FILE *fp;
    int main(){
    fp = fopen("MathPic.ppm","wb");
    fprintf(fp, "P6\n%d %d\n255\n", DIM1, DIM2);
    for(int j=0;j<DIM2;j++)
    for(int i=0;i<DIM1;i++)
    pixel_write(i,j);
    fclose(fp);
    system("pause");
    return 0;
    }
    void pixel_write(int i, int j){
    static unsigned char color[3];
    color[0] = RD(i,j)&255;
    color[1] = GR(i,j)&255;
    color[2] = BL(i,j)&255;
    fwrite(color, 1, 3, fp);
    }
    

    代码的输出结果ppm经过XnViewConvert转换成png格式之后是这样的:
    这里写图片描述

    foo bar foo
    foo bar foo

    Edit

    【稍安勿躁,正在加班加点更新】


    1. “相濡以沫,不如相忘于江湖。” 我发现庄子就像读过鲁迅的《伤逝》一样,早在几千年前就建议好了该放下的时候要果断放下,可还是有人执迷不悟。——这就是古人的大智慧。“难道我们还不如古人吗?”(后面这个反问句在我高中一同学的作文里常用,每次想起他在班里当众读自己作文里这一句时气势汹汹的样子,我都想回答“是的。在很多方面。”这也是我瞧不起一些文科生和文科公知的原因: 立论完全罔顾事实,单纯依赖辩论技巧. 你他么这样自欺欺人能解决黎曼猜想还是哥德巴赫猜想?)
    2. 我觉得刚才我写到这里没更新的时候,肯定有点进来的人看了很失望,因为实际上到此为止,除了画了个椭圆,我啥也没讲。会不会觉得博主不太靠谱?那一定是因为你自己更不靠谱!我觉得评价一个人靠谱与否的唯一标准是看此人是不是删过facebook
    3. “拓扑学”听上去挺抽象,但我觉得数学之所以看上去让人望而却步,除了某些基础性的基本功的确需要积累和修炼之外,大部分因为老师的方法有问题。 在深入了解这个概念之前就知道了“判断是内点或外点”时这个概念该怎么用——也就是实际使用的方法是很简单的——,不过,我边写边完善的过程中发现有更多相关而有趣的不同表述,比我原先想象的精彩得多,需要自己细细琢磨,所以更新的速度可能会变慢。学习速度更快的不妨自己先看维基。
    展开全文
  • 分段三阶贝塞尔曲线的光滑连续性条件 1. 贝塞尔曲线简介 [1] 计算机图形学中有一类很常用的曲线,俗称贝塞尔曲线。1962年,法国数学家Pierre Bézier 第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式...

    分段三阶贝塞尔曲线的光滑连续性条件

    1. 贝塞尔曲线简介 [1]

    计算机图形学中有一类很常用的曲线,俗称贝塞尔曲线。1962年,法国数学家Pierre Bézier 第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名是为贝塞尔曲线。 很多程序语言都有实现贝塞尔曲线的API,而该曲线本身也拥有强大的近似其它曲线的能力,即使一条不能够胜任,那么分段的多条贝塞尔曲线也足够用来近似我们想绘制的曲线。

    这里给出贝塞尔曲线的一般公式:
    P ( t ) = ∑ i = 0 n B i , n ( t ) P i P(t)=\sum_{i=0}^n{B_{i,n}(t)\mathbf{P_i}} P(t)=i=0nBi,n(t)Pi
    其中:
    B i , n ( t ) = n ! i ! ( n − i ) ! t i ( 1 − t ) n − i , t ∈ [ 0 , 1 ] B_{i,n}(t)=\frac{n!}{i!(n-i)!}t^i(1-t)^{n-i},t\in[0,1] Bi,n(t)=i!(ni)!n!ti(1t)ni,t[0,1]
    对于以$ P_{i-1} 和 和 P_{i} 作 为 起 点 和 终 点 的 三 阶 贝 塞 尔 曲 线 段 , 具 有 两 个 控 制 点 作为起点和终点的三阶贝塞尔曲线段,具有两个控制点 线 C_{i,1} 、 、 C_{i,2} $,方程为:
    P i − 1 , i ( t ) = P i − 1 + ( − 3 P i − 1 + 3 C i , 1 ) t + ( 3 P i − 1 − 6 C i , 1 + 3 C i , 2 ) t 2 + ( − P i − 1 + 3 C i , 1 − 3 C i , 2 + P i ) t 3 P_{i-1,i}(t)= P_{i-1} +(- 3P_{i-1} + 3C_{i,1} )t +( 3P_{i-1} - 6C_{i,1} + 3C_{i,2} )t^2 +(- P_{i-1} + 3C_{i,1} - 3C_{i,2} + P_{i})t^3 Pi1,i(t)=Pi1+(3Pi1+3Ci,1)t+(3Pi16Ci,1+3Ci,2)t2+(Pi1+3Ci,13Ci,2+Pi)t3
    对应的方程一阶导数即为:
    d P i − 1 , i ( t ) d t = ( − 3 P i − 1 + 3 C i , 1 ) + ( 6 P i − 1 − 12 C i , 1 + 6 C i , 2 ) t + ( − 3 P i − 1 + 9 C i , 1 − 9 C i , 2 + 3 P i ) t 2 \frac{dP_{i-1,i}(t)}{dt} = (- 3P_{i-1} + 3C_{i,1} ) +( 6P_{i-1} -12C_{i,1} + 6C_{i,2} )t +(- 3P_{i-1} + 9C_{i,1} - 9C_{i,2} + 3P_{i})t^2 dtdPi1,i(t)=(3Pi1+3Ci,1)+(6Pi112Ci,1+6Ci,2)t+(3Pi1+9Ci,19Ci,2+3Pi)t2

    2. 光滑连续性条件

    要求曲线段$ P_{i-1,i}(t) 和 和 P_{i,i+1}(t) 光 滑 连 续 , 就 是 要 求 两 曲 线 段 在 点 光滑连续,就是要求两曲线段在点 线 P_{i} $处可导,则一充分非必要条件为:
    d P i − 1 , i ( t ) d t ∣ t = 1 = d P i , i + 1 ( t ) d t ∣ t = 0 \frac{dP_{i-1,i}(t)}{dt}|_{t=1}=\frac{dP_{i,i+1}(t)}{dt}|_{t=0} dtdPi1,i(t)t=1=dtdPi,i+1(t)t=0
    化简为:
    P i − C i , 2 = C i + 1 , 1 − P i \mathbf{P_{i}}-\mathbf{C_{i,2}}=\mathbf{C_{i+1,1}}-\mathbf{P_{i}} PiCi,2=Ci+1,1Pi
    即是矢量$ \mathbf{C_{i,2}}\mathbf{P_{i}} $ 与矢量 $ \mathbf{P_{i}}\mathbf{C_{i+1,1}} $相等。

    3. 通过点的分段三阶贝塞尔曲线绘制方案

    3.1 基本绘制方法

    由于得到的光滑连续性条件为矢量$ \mathbf{C_{i,2}}\mathbf{P_{i}} $ 与矢量 $ \mathbf{P_{i}}\mathbf{C_{i+1,1}} $相等,但其大小和方向未知,可以采取以下方案绘制光滑连续的分段三阶贝塞尔曲线:

    1. 计算相邻三点$ P_{i-1} 、 、 P_{i} 和 和 P_{i+1} 的 中 点 的中点 P_{i-1,i}^{avg} 和 和 P_{i,i+1}^{avg} $
    2. 计算中点的中点$ P_{i-1,i,i+1}^{avg} $
    3. 将点$ P_{i-1,i}^{avg} 和 和 P_{i,i+1}^{avg} 沿 矢 量 沿矢量 沿 \mathbf{P_{i-1,i,i+1}^{avg} P_{i}}$进行平移
    4. 得到的两点就作为前一段曲线的第二控制点$ C_{i,2} 和 后 一 段 曲 线 的 第 一 控 制 点 和后一段曲线的第一控制点 线 C_{i+1,1} $

    通过上述方式可以得到:
    C i , 2 = P i − 1 4 ( P i + 1 − P i − 1 ) C_{i,2}=P_{i}-\frac{1}{4}(P_{i+1}-P_{i-1}) Ci,2=Pi41(Pi+1Pi1)
    C i + 1 , 1 = P i + 1 4 ( P i + 1 − P i − 1 ) C_{i+1,1}=P_{i}+\frac{1}{4}(P_{i+1}-P_{i-1}) Ci+1,1=Pi+41(Pi+1Pi1)

    3.2 控制点伸缩方法

    对$ P_{i} 点 周 围 的 控 制 点 点周围的控制点 C_{i,2} 和 和 C_{i+1,1} 进 行 内 缩 或 外 扩 , 可 以 通 过 将 点 沿 矢 量 进行内缩或外扩,可以通过将点沿矢量 沿\mathbf{ P_{i-1,i}^{avg} P_{i,i+1}^{avg}} 左 右 平 移 得 到 。 要 使 控 制 点 线 段 左右平移得到。 要使控制点线段 使线 C_{i,2}C_{i+1,1} 为 原 来 的 为原来的 k 倍 , 若 正 方 向 指 向 点 倍,若正方向指向点 P_{i} $,有左侧控制点平移矢量:
    V l e f t = 1 − k 4 ( P i + 1 − P i − 1 ) V_{left}=\frac{1-k}{4}(P_{i+1}-P_{i-1}) Vleft=41k(Pi+1Pi1)
    右侧控制点平移矢量:
    V r i g h t = − 1 ⋅ 1 − k 4 ( P i + 1 − P i − 1 ) V_{right}=-1\cdot\frac{1-k}{4}(P_{i+1}-P_{i-1}) Vright=141k(Pi+1Pi1)
    则:
    C i , 2 = C i , 2 + V l e f t = P i − k 4 ( P i + 1 − P i − 1 ) C_{i,2}=C_{i,2}+V_{left}=P_{i}-\frac{k}{4}(P_{i+1}-P_{i-1}) Ci,2=Ci,2+Vleft=Pi4k(Pi+1Pi1)
    C i + 1 , 1 = C i + 1 , 1 + V r i g h t = P i + k 4 ( P i + 1 − P i − 1 ) C_{i+1,1}=C_{i+1,1}+V_{right}=P_{i}+\frac{k}{4}(P_{i+1}-P_{i-1}) Ci+1,1=Ci+1,1+Vright=Pi+4k(Pi+1Pi1)
    其中
    k ∈ ( 0 , 1 ] k\in(0,1] k(0,1]时为内缩,
    k ∈ [ 1 , + ∞ ) k\in[1,+\infty) k[1,+)时为外扩。
    一般 k k k [ 0.4 , 0.6 ] [0.4,0.6] [0.4,0.6]较为合适。

    3.3 非封闭的分段三阶贝塞尔曲线

    对于封闭的分段三阶贝塞尔曲线通过点集$ \mathbf{P_i}={i|i=0,1,2,…,n} , 由 于 其 首 尾 相 连 , 可 以 看 作 在 点 ,由于其首尾相连,可以看作在点 P_0 前 有 点 前有点 P_n , 在 点 ,在点 P_n 后 有 点 后有点 P_0$,从而确定第 1 1 1个点的第一控制点 C 0 , 1 C_{0,1} C0,1和第 n n n个点的第二控制点 C n , 2 C_{n,2} Cn,2
    而对于非封闭的分段三阶贝塞尔曲线通过点集$ \mathbf{P_i}={i|i=0,1,2,…,n}$,无法确定第 1 1 1个点的第一控制点 C 0 , 1 C_{0,1} C0,1和第 n n n个点的第二控制点 C n , 2 C_{n,2} Cn,2,暂时的解决方案是:
    C 0 , 1 = C 0 , 2 , C n , 1 = C n , 2 C_{0,1}=C_{0,2},C_{n,1}=C_{n,2} C0,1=C0,2,Cn,1=Cn,2

    3.4 三阶贝塞尔曲线段的边界求解

    求解三阶贝塞尔曲线段的边界,就是求解方程的一阶导数为 0 0 0的点:
    ( − 3 P i − 1 + 3 C i , 1 ) + ( 6 P i − 1 − 12 C i , 1 + 6 C i , 2 ) t + ( − 3 P i − 1 + 9 C i , 1 − 9 C i , 2 + 3 P i ) t 2 = 0 (- 3P_{i-1} + 3C_{i,1} ) +( 6P_{i-1} -12C_{i,1} + 6C_{i,2} )t +(- 3P_{i-1} + 9C_{i,1} - 9C_{i,2} + 3P_{i})t^2 =0 (3Pi1+3Ci,1)+(6Pi112Ci,1+6Ci,2)t+(3Pi1+9Ci,19Ci,2+3Pi)t2=0
    值得注意:上下边界用点$ P_{i} 的 的 y 值 求 解 , 左 右 边 界 用 点 值求解,左右边界用点 P_{i} 的 的 x $值求解;方程存在二次项为 0 0 0的情况,所以需要判断二次项是否为 0 0 0
    下面呈现具体计算代码:

    //首先定义一个边界类,用以方便计算曲线边界
    public class Boundary
    {
        public Boundary(double xMax = Double.NaN, double xMin = Double.NaN, double yMax = Double.NaN, double yMin = Double.NaN)
        {
            XMax = xMax;
            XMin = xMin;
            YMax = yMax;
            YMin = yMin;
        }
    
        public Boundary(Point point1, Point point2)
        {
            if (point1.X >= point2.X)
            {
                XMax = point1.X;
                XMin = point2.X;
            }
            else
            {
                XMax = point2.X;
                XMin = point1.X;
            }
            if (point1.Y >= point2.Y)
            {
                YMax = point1.Y;
                YMin = point2.Y;
            }
            else
            {
                YMax = point2.Y;
                YMin = point1.Y;
            }
        }
    
        public double XMax { get; set; }
        public double XMin { get; set; }
        public double YMax { get; set; }
        public double YMin { get; set; }
    
        public void Resize(double xMax, double xMin, double yMax, double yMin)
        {
            XMax = xMax;
            XMin = xMin;
            YMax = yMax;
            YMin = yMin;
        }
    
        public void TryInclude(params Point[] points)
        {
            var length = points.Length;
            if (length <= 0 || points == null)
            {
                return;
            }
    
            double xmax;
            double xmin;
            double ymax;
            double ymin;
            bool isValueInvalid = Boundary.IsValueInvalid(this);
            if (isValueInvalid)
            {
                xmax = xmin = points[0].X;
                ymax = ymin = points[0].Y;
            }
            else
            {
                xmax = this.XMax;
                xmin = this.XMin;
                ymax = this.YMax;
                ymin = this.YMin;
            }
    
            double x;
            double y;
            for (int i = 0; i < length; i++)
            {
                x = points[i].X;
                y = points[i].Y;
                if (x > xmax)
                {
                    xmax = x;
                }
                if (x < xmin)
                {
                    xmin = x;
                }
                if (y > ymax)
                {
                    ymax = y;
                }
                if (y < ymin)
                {
                    ymin = y;
                }
            }
    
            this.XMax = xmax;
            this.XMin = xmin;
            this.YMax = ymax;
            this.YMin = ymin;
        }
    
        public void Merge(Boundary boundary)
        {
            bool isValueInvalid = Boundary.IsValueInvalid(this);
            if (!isValueInvalid)
            {
                if (Boundary.IsValueInvalid(boundary))
                {
                    return;
                }
                if (boundary.XMax > this.XMax)
                {
                    this.XMax = boundary.XMax;
                }
                if (boundary.XMin < this.XMin)
                {
                    this.XMin = boundary.XMin;
                }
                if (boundary.YMax > this.YMax)
                {
                    this.YMax = boundary.YMax;
                }
                if (boundary.YMin < this.YMin)
                {
                    this.YMin = boundary.YMin;
                }
            }
            else
            {
                this.XMax = boundary.XMax;
                this.XMin = boundary.XMin;
                this.YMax = boundary.YMax;
                this.YMin = boundary.YMin;
            }
        }
        
        public static bool IsValueInvalid(Boundary boundary)
        {
            if (Double.IsNaN(boundary.XMax))
            {
                return true;
            }
            if (Double.IsNaN(boundary.XMin))
            {
                return true;
            }
            if (Double.IsNaN(boundary.YMax))
            {
                return true;
            }
            if (Double.IsNaN(boundary.YMin))
            {
                return true;
            }
            return false;
        }
    }
    //接下来给出具体贝塞尔曲线边界的计算方法,该方法用以返回某段曲线的边界
    private Boundary CalculateBezierSegmentBoundary(Point p0, Point c1, Point c2, Point p1)
    {
        Boundary boundaryBS = new Boundary(p0, p1);
        double AY = 3 * c1.Y - 3 * c2.Y + p1.Y - p0.Y;
        double BY = 3 * (p0.Y + c2.Y - 2 * c1.Y);
        double CY = 3 * (c1.Y - p0.Y);
        double DY = p0.Y;
    
        double AX = 3 * c1.X - 3 * c2.X + p1.X - p0.X;
        double BX = 3 * (p0.X + c2.X - 2 * c1.X);
        double CX = 3 * (c1.X - p0.X);
        double DX = p0.X;
    
        double ay = 3 * AY;
        double by = 2 * BY;
        double cy = CY;
        double deltay = Math.Pow(by, 2) - 4 * ay * cy;
    
        double ax = 3 * AX;
        double bx = 2 * BX;
        double cx = CX;
        double deltax = Math.Pow(bx, 2) - 4 * ax * cx;
    
        bool IsAYApproximateZero = (ay > -1 * 1e-10) && (ay < 1e-10);
        bool IsAXApproximateZero = (ax > -1 * 1e-10) && (ax < 1e-10);
        if (IsAYApproximateZero || IsAXApproximateZero)
        {
            if (IsAYApproximateZero)
            {
                double ty = -1 * cy / by;
                if (ty > 0 && ty < 1)
                {
                    double x = AX * ty * ty * ty + BX * ty * ty + CX * ty + DX;
                    double y = AY * ty * ty * ty + BY * ty * ty + CY * ty + DY;
                    boundaryBS.TryInclude(new Point(x, y));
                }
            }
            if (IsAXApproximateZero)
            {
                double tx = -1 * cx / bx;
                if (tx > 0 && tx < 1)
                {
                    double x = AX * tx * tx * tx + BX * tx * tx + CX * tx + DX;
                    double y = AY * tx * tx * tx + BY * tx * tx + CY * tx + DY;
                    boundaryBS.TryInclude(new Point(x, y));
                }
            }
            return boundaryBS;
        }
        bool IsDeltaYGreaterThanZero = deltay > 0;
        bool IsDeltaXGreaterThanZero = deltax > 0;
        bool IsDeltaYApproximateZero = (deltay > -1 * 1e-10) && (deltay < 1e-10);
        bool IsDeltaXApproximateZero = (deltax > -1 * 1e-10) && (deltax < 1e-10);
        if (IsDeltaYGreaterThanZero || IsDeltaXGreaterThanZero)
        {
            if (!IsAYApproximateZero)
            {
                if (IsDeltaYGreaterThanZero)
                {
                    double t1y = (-1 * by + Math.Pow(deltay, 0.5)) / (2 * ay);
                    double t2y = (-1 * by - Math.Pow(deltay, 0.5)) / (2 * ay);
                    if (t1y > 0 && t1y < 1)
                    {
                        double x = AX * t1y * t1y * t1y + BX * t1y * t1y + CX * t1y + DX;
                        double y = AY * t1y * t1y * t1y + BY * t1y * t1y + CY * t1y + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                    if (t2y > 0 && t2y < 1)
                    {
                        double x = AX * t2y * t2y * t2y + BX * t2y * t2y + CX * t2y + DX;
                        double y = AY * t2y * t2y * t2y + BY * t2y * t2y + CY * t2y + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                }
            }
            if (!IsAXApproximateZero)
            {
                if (IsDeltaXGreaterThanZero)
                {
                    double t1x = (-1 * bx + Math.Pow(deltax, 0.5)) / (2 * ax);
                    double t2x = (-1 * bx - Math.Pow(deltax, 0.5)) / (2 * ax);
                    if (t1x > 0 && t1x < 1)
                    {
                        double x = AX * t1x * t1x * t1x + BX * t1x * t1x + CX * t1x + DX;
                        double y = AY * t1x * t1x * t1x + BY * t1x * t1x + CY * t1x + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                    if (t2x > 0 && t2x < 1)
                    {
                        double x = AX * t2x * t2x * t2x + BX * t2x * t2x + CX * t2x + DX;
                        double y = AY * t2x * t2x * t2x + BY * t2x * t2x + CY * t2x + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                }
            }
            return boundaryBS;
        }
        else if (IsDeltaYApproximateZero || IsDeltaXApproximateZero)
        {
            if (!IsAYApproximateZero)
            {
                if (IsDeltaYApproximateZero)
                {
                    double ty = -1 * by / (2 * ay);
                    if (ty > 0 && ty < 1)
                    {
                        double x = AX * ty * ty * ty + BX * ty * ty + CX * ty + DX;
                        double y = AY * ty * ty * ty + BY * ty * ty + CY * ty + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                }
            }
            if (!IsAXApproximateZero)
            {
                if (IsDeltaXApproximateZero)
                {
                    double tx = -1 * bx / (2 * ax);
                    if (tx > 0 && tx < 1)
                    {
                        double x = AX * tx * tx * tx + BX * tx * tx + CX * tx + DX;
                        double y = AY * tx * tx * tx + BY * tx * tx + CY * tx + DY;
                        boundaryBS.TryInclude(new Point(x, y));
                    }
                }
            }
            return boundaryBS;
        }
        else
        {
            return boundaryBS;
        }
    }
    //最后可以使用Boundary类中的Merge方法合并边界以计算所有分段三阶贝塞尔曲线边界
    
    
    展开全文
  • 贝塞尔曲线及实践案例

    千次阅读 2022-03-15 14:26:54
    贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们...

    1. 前言

    贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。

    2. 介绍

    2.1 一阶贝济埃曲线

    一阶贝济埃曲线的公式如下:

     B(t)=(1-t)P_0+tP_1,t属于0-1
    

    P0为起始点,P1为终点,t 表示当前时间,B(t)表示公式的结果值。其实也就是一条从P0到P1的直线上,匀速运动的点值。

    2.2 二阶贝塞尔曲线

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x1sAavqD-1647325585493)(images/screenshot_1647310332528.png)]

    在这里插入图片描述

    这条曲线的构成也就是每个t时刻,Q0和Q1的所属的直线的的t时刻的距离的点,这里也就是B。不妨将上面这个图简单标注下:
    在这里插入图片描述

    也就是在从P0到P1,进行匀速运动,在t=0.25的时刻走到Q0,类似的,从P1到P2经过匀速运动,在t=0.25的时刻走到Q1,对于Q0到Q1,经过匀速运动,在t=0.25的时刻走到B。而B也就是二阶贝塞尔曲线上的点。

    2.3 三阶贝塞尔曲线

    在这里插入图片描述

    也就是说此时有两个控制点,对应着也就是三根连着的线段,类似的我们可以得到最终的t点:
    在这里插入图片描述

    那么,根据上面的规则,我们可以自己来实现一下贝赛尔曲线的计算方式,并将曲线绘制出来。

    3. 一、二、三阶贝塞尔曲线实现

    定义为:

    class Point(var x: Float, var y: Float){
    }
    
    /**
     * 得到贝赛尔曲线上的点集
     * @param points 起始、控制和终止点坐标
     * @param number 需要计算的贝赛尔曲线上的点的个数
     * @return 返回路径
     */
    private fun getBezierPointsPath(points: Array<Point>, number: Int): Path{
        val path = Path()
        for (time in 0 until number){
            val t = time * 1f / number
            val point = calcPoint(points, t)
            if(time == 0){
                path.moveTo(point.x, point.y)
            } else {
                path.lineTo(point.x, point.y)
            }
            Log.e("TAG", "getBezierPointsPath: ${point.x} , ${point.y}", )
        }
        return path
    }
    
    
    /**
     * 计算在t时刻上,位于贝赛尔曲线上的点的坐标
     * @param points 点的集合
     * @param t 时刻,属于0-1
     * @return 点坐标 Point
     */
    private fun calcPoint(points: Array<Point>, t: Float): Point{
        // 分别求任意两个点之间的在t时刻运动的距离
        // 任意两点,按照顺序分别为始和终
        var index = 0
        var len = points.size - 1
        while (index < len){
            points[index].x = getValueByTime(points[index].x, points[index + 1].x, t)
            points[index].y = getValueByTime(points[index].y, points[index + 1].y, t)
            index++
            if(index == len){
                index = 0
                len--
            }
        }
        return points[0]
    }
    
    /**
     * 定义匀速运动的计算坐标
     * @param start 开始的位置
     * @param end 结束的位置
     * @param time 运动的时间,范围0-1
     * @return time时刻的运动位置
     */
    private fun getValueByTime(start: Float, end: Float, time: Float): Float{
        return start + (end - start) * time
    }
    

    然后使用:

    // 绘图方法
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.apply {
            val points = arrayOf(Point(200f, 400f), Point(100f, 20f), Point(500f, 20f), Point(800f, 400f))
            val numberOfPoint = 100
            mPath = getBezierPointsPath(points, numberOfPoint)
            drawPath(mPath, mPaint)
        }
    }
    

    在这里插入图片描述

    很明显,这里细粒度不够。可以把numberOfPoint 设置的更大些。当设置为1000的时候:
    在这里插入图片描述

    当然这里可以使用arrayOf的时候添加更多的点,以做到更加高阶的贝塞尔曲线,比如简单修改一下:

    val points = arrayOf(Point(200f, 400f),
        Point(100f, 20f),
        Point(500f, 20f),
        Point(800f, 400f),
        Point(1000f, 20f)
    )
    

    也就是对应三个控制点,对应四阶本塞尔曲线,对应效果:
    在这里插入图片描述
    当然,在系统中其实也提供了一、二、三阶的贝赛尔曲线的API,所以通常直接调用即可。对应的如下:

    • mPath.lineTo:进行直线绘制 ;
    • mPath.quadTo(x1, y1, x2, y2) :生成二次贝塞尔曲线,(x1,y1) 为控制点,(x2,y2)为结束点 ;
    • mPath.cubicTo(x1, y1, x2, y2, x3, y3):生成三次贝塞尔曲线, (x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点;

    4. 案例

    /**
     * 学习波浪效果,其实也就是移动类似于正弦的连续图像,带来的视觉效果
     * @author 梦否
     * 2022年3月15日
     */
    class WaterRippleView : View {
        constructor(context: Context?) : super(context) {
            init()
        }
    
        constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
            init()
        }
    
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
            context,
            attrs,
            defStyleAttr
        ) {
            init()
        }
    
        private lateinit var mPath: Path
        private lateinit var mPaint: Paint
        private lateinit var points1: Array<MyPoint>
        private lateinit var points2: Array<MyPoint>
    
        class MyPoint(var x: Float, var y: Float)
    
        /**
         * 初始化方法
         */
        private fun init() {
            mPath = Path()
            mPaint = Paint()
            mPaint.isDither = true
            mPaint.isAntiAlias = true
            mPaint.strokeWidth = 5f
            mPaint.color = Color.GRAY
            mPaint.style = Paint.Style.FILL
    
            val viewWidth = resources.displayMetrics.widthPixels
            points1 = arrayOf(
                MyPoint(0f * viewWidth, 200f),
                MyPoint(.33f * viewWidth, 20f),
                MyPoint(.66f * viewWidth, 360f),
                MyPoint(1f * viewWidth, 200f)
            )
            points2 = arrayOf(
                MyPoint(-1f * viewWidth, 200f),
                MyPoint(-.66f * viewWidth, 20f),
                MyPoint(-.33f * viewWidth, 360f),
                MyPoint(0f * viewWidth, 200f),
            )
    
            // 三阶贝塞尔曲线,传入0,也就是初始时刻
            updatePathByDistance(0f)
        }
    
        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
    
            canvas?.apply {
                drawPath(mPath, mPaint)
            }
    
        }
    
        /**
         * 根据距离来进行更新在贝赛尔曲线中的点的坐标值
         * @param distance 传入的距离
         */
        private fun updatePathByDistance(distance: Float) {
            // 重置
            mPath.reset()
            // 设置
            mPath.moveTo(points2[0].x, points2[0].y)
            mPath.cubicTo(
                points2[1].x + distance,
                points2[1].y,
                points2[2].x + distance,
                points2[2].y,
                points2[3].x + distance,
                points2[3].y
            )
    
            mPath.cubicTo(
                points1[1].x + distance,
                points1[1].y,
                points1[2].x + distance,
                points1[2].y,
                points1[3].x + distance,
                points1[3].y
            )
    
            val y = resources.displayMetrics.heightPixels
            mPath.lineTo(points1[3].x, y.toFloat())
            mPath.lineTo(points2[0].x + distance,  y.toFloat())
            mPath.lineTo(points2[0].x + distance, points2[0].y)
        }
    
        /**
         * 一直移动绘制的两个类似于正弦函数的路径
         */
        var startedMove = false
        private fun startMove() {
            startedMove = true
            val animator = ValueAnimator.ofFloat(0f, resources.displayMetrics.widthPixels.toFloat())
            animator.duration = 800
            // 线性插值器,使之匀速运动
            animator.interpolator = LinearInterpolator()
            // 循环
            animator.repeatCount = ValueAnimator.INFINITE
            animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
                override fun onAnimationUpdate(animation: ValueAnimator?) {
                    val value = animator.getAnimatedValue()
                    updatePathByDistance(value as Float)
                    // 重绘
                    invalidate()
                }
            })
            animator.start()
        }
    
        override fun onTouchEvent(event: MotionEvent?): Boolean {
            super.onTouchEvent(event)
            var flag = false
            when (event?.action) {
                MotionEvent.ACTION_DOWN -> {
                    flag = true
                    if(!startedMove) startMove()
                }
                MotionEvent.ACTION_MOVE,
                MotionEvent.ACTION_UP -> {
                    flag = false
                }
            }
            return flag
        }
    
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            val minHeight = dp2px(300)
            val minWidth = dp2px(500)
            val widthSize = getMeasureSize(widthMeasureSpec, minWidth.toInt())
            val heightSize = getMeasureSize(heightMeasureSpec, minHeight.toInt())
            setMeasuredDimension(widthSize, heightSize)
        }
    
        /**
         * 计算高度和宽度
         */
        private fun getMeasureSize(Spec: Int, minValue: Int): Int {
            var result = 0
            // 获取模式
            val mode = MeasureSpec.getMode(Spec)
            val size = MeasureSpec.getSize(Spec)
    
            // 判断一下
            when (mode) {
                MeasureSpec.AT_MOST -> {
                    result = Math.min(size, minValue)
                }
                MeasureSpec.UNSPECIFIED -> {
                    result = minValue
                }
                MeasureSpec.EXACTLY -> {
                    result = size
                }
            }
            return result
        }
    
        /**
         * dp转换为px
         */
        private fun dp2px(size: Int): Float {
            return resources.displayMetrics.density * size
        }
    }
    

    5. 后记

    当然关于贝赛尔曲线的应用远不止如此。比如:Android开发之贝塞尔曲线进阶篇(仿直播送礼物,饿了么购物车动画),感兴趣的可以查阅原文。

    展开全文
  • OpenCV如何提取图片中曲线

    千次阅读 2020-12-08 14:10:45
    简单介绍在实际的应用中,我们常常需要对图像中的曲线进行描述、处理,这个曲线可以是轮廓,骨架或者其他。可以用deque 描述曲线,接下来简单介绍下如何从图片中搜索这些曲线并保存。首先,输入的图片是一张二值图片...
  • 缓和曲线——回旋曲线

    千次阅读 2022-02-21 14:33:26
    回旋线是半径从无穷大一直变化到一定设计值的一段弧线。回旋线是曲率随着曲线长度成比例变化的曲线
  •  对于通常情况,我考虑使用变号法则来判断交点(也就是高数里面“连续函数变号端点内存在零点”),对于上面说的特殊情况,那么预先处理,比如先看是否存在eps内的,或者为零的结点,有则直接记录,没有的话,通过...
  • 如何判断轮廓是否为圆? 如何判断轮廓是否为圆? 判断一个轮廓是否为圆?这看似简单的问题,在opencv中并没有现成的函数。当我真正想运用的时候,却发现还是有许多内容在里面的。 比如这幅图片,由于瓶口...
  • 参数连续性:组合参数曲线在连接处具有直到n阶连续导矢,即n阶连续可微,称为n阶参数连续性CnC^nCn 几何连续性:组合曲线在连接处满足不同于CnC^nCn的某一组约束条件,称为具有n阶几何连续性GnG^nGn。 对于参数t∈...
  • 转自:Spline导数及曲率计算 1 概述  曲率的公式为: ... 根据参考资料[5]的提示,可以使用csape()对离散点进行Spline插值,然后使用fnder()对得到Spline曲线求导,最后使用fnval()对导数求值即可。 [p
  • cv曲线(电化学cv曲线分析)

    千次阅读 2021-03-06 17:46:41
    什么是cv曲线CV 曲线是由控制顶点( CV)控制的 NURBS 曲线。 CV 不位于曲线上。 它们定义一个包含曲线的控制晶格。 每一 CV 具有一个权重,可通过调整它来更改曲线。 在创建 .就 CREAT菜单栏里的那两个工具名称上的...
  • 曲线积分 在区域 内与路径无关的充分必要条件是:对于 内任意一条简单逐段光滑闭曲线 ,沿 的曲线积分为零,即: 既然该曲线积分在对应区域内任意一条闭合曲线积分都等于零,又因为对于 之间任意给定的两条路径,...
  • C#_CAD二次开发_快速选择dwg中的所有多段线Polyline和样条曲线Spline.cpp(两个函数)
  • 本文介绍了利用导数判断函数单调性、凹凸性、极值相关的概念和定理,通过本文的介绍,可以熟悉通过导数判断函数单调性、凹凸性、极值以及求最值的原理和方法。最后,通过一阶导数和二阶导数确定了函数的单调性、凹凸...
  • 生物统计分析之ROC曲线分析

    千次阅读 2021-05-10 10:26:26
    受试者工作特征曲线( receiver operating characteristic curve , ROC 曲线),又称为感受性曲线( sensitivity curve ),是比较诊断测试的一种方法。随着接受者灵敏度的提高,假阳性的数量会随之增加。 因此, ROC ...
  • 判断一个点是否在不规则图形中

    千次阅读 2019-08-20 20:38:10
    判断一个点是否在多边形内部 - 射线法思路 比如说,我就随便涂了一个多边形和一个点,现在我要给出一种通用的方法来判断这个点是不是在多边形内部(别告诉我用肉眼观察……)。 首先想到的一个解法是从这个点做一条...
  • 针对鞋楦高速加工要求,提出了采用B样条曲线对离散数据进行刀具半径偏置的方法....针对二阶连续曲线拐点的偏置计算误差,对偏置曲线自相交现象进行了判断和处理,解决了样条曲线高速加工存在的过切和少切问题.
  • 博主声明: 转载请在开头附加本文链接及作者信息,并... 直接步入正题,我们要实现的是一个 Android 客户端应用里面的一种点赞效果,比如你点一下那个爱心型的图片,就会产生一个小爱心,而且会以曲线的方式进行上...
  • 曲线的凹凸性与拐点

    万次阅读 多人点赞 2018-01-13 11:30:54
    一个函数在上升或下降的过程中,常常会有一个...设f(x)f(x)在区间II上连续,如果对II上任意两点x1,x2x_1, x_2恒有f(x1+x22)f(x1)+f(x2)2f(\frac{x_1+x_2}{2}) 那么称f(x)f(x)在II上的图形是(向上)凹的(或凹弧); 如果
  • 高等数学-求曲线拐点

    千次阅读 2022-03-27 20:04:21
    一、拐点的定义  拐点:连续曲线上凹与凸的... 解:先求出f’’(x) = 0 的根,判断求出的根是否符合。然后求y在拐点的斜率,代入拐点即可求出切线方程。  为什么要舍去x=-1。因为原函数y里面有lnx,x需要大于0! ...
  • 7.3 曲线连续性 当许多参数曲线 首尾相连 构成一条曲线时,如何保证各个曲线段在连接处具有合乎要求的连续性是一个重要问题。 假定参数曲线段 以 参数形式进行描述: 这里讨论参数曲线两种意义上的连续...
  • 曲线相似计算方法

    千次阅读 2021-02-05 12:28:54
    曲线相似性计算,如果两条之间存在直接影响,更要关注特征的连续性,如果两条受同一条影响,更要关注特征的离散最大性。 设xn为A的波动数据序列,yn为B的波动数据序列,其中n=1…N。A与B的相关系数可以通过如下公式...
  • matlab开环幅相曲线

    千次阅读 2021-04-20 01:13:33
    – K 的变化对应于对数幅频曲线上下移动,而相 频曲线不变。 – 一张图上...180 0 6 频率响应分析法 22 3.7 用Matlab绘制频域特性图 ? sys = tf(num......2、实验主要仪器设备和材料:计算机一台 matlab 软件 2010a ...
  • 昆仑通态历史曲线如何组态呢?

    千次阅读 2021-01-15 22:52:34
    绘制了历史曲线后,在历史曲线上双击鼠标左键,将弹出“历史曲线构件属性设置对话框”。历史曲线构件属性设置对话框由六个属性卡片“基本属性”、“存盘属性”、“标注属性”、“曲线标识”、“输出信息”、“高级...
  • 上升沿子程序

    2013-03-22 13:21:44
    直接调用附件的程序就可以用了,很方便!我自己编写的,供大家参考。学习Labview的必需品。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,777
精华内容 11,910
关键字:

判断曲线是否连续