bezier曲线拟合椭圆弧线

2024-03-20 20:04

本文主要是介绍bezier曲线拟合椭圆弧线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

椭圆弧线用bezier曲线拟合 。
先计算出 椭圆中心 起始角度 旋转角度

S t e p 1 : C o m p u t e ( x 1 ′ , y 1 ′ ) Step 1: Compute(x'_1, y'_1) Step1:Compute(x1,y1)
( x 1 ′ y 1 ′ ) = ( cos ⁡ φ sin ⁡ φ − sin ⁡ φ cos ⁡ φ ) ⋅ ( x 1 − x 2 2 y 1 − y 2 2 ) \begin{pmatrix} x'_1 \\ \\ y'_1 \end{pmatrix} = \begin{pmatrix} \cos\varphi & \sin\varphi \\ \\ -\sin\varphi & \cos\varphi \end{pmatrix} \cdot \begin{pmatrix} \dfrac{ x_1-x_2}{2} \\ \\ \dfrac{ y_1-y_2}{2} \end{pmatrix} x1y1 = cosφsinφsinφcosφ 2x1x22y1y2

S t e p 2 : C o m p u t e ( c x ′ , c y ′ ) Step 2: Compute(c'_x, c'_y) Step2:Compute(cx,cy)
( c x ′ c y ′ ) = ± r x 2 y y 2 − r x 2 ( y 1 ′ ) 2 − r y 2 ( x 1 ′ ) 2 r x 2 ( y 1 ′ ) 2 + r y 2 ( x 1 ′ ) 2 ( r x y 1 ′ r y − r y x 1 ′ r x ) \begin{pmatrix} c'_x \\ \\ c'_y \end{pmatrix} = \pm \sqrt { \dfrac{ r^2_x y^2_y - r^2_x(y'_1)^2 - r^2_y (x'_1)^2} {r^2_x (y'_1)^2 + r^2_y(x'_1)^2 } } \begin{pmatrix} \dfrac{ r_xy'_1}{r_y} \\ \\ -\dfrac{ r_y x'_1}{r_x} \end{pmatrix} cxcy =±rx2(y1)2+ry2(x1)2rx2yy2rx2(y1)2ry2(x1)2 ryrxy1rxryx1

在这里插入图片描述

然后拟合
在这里插入图片描述

在这里插入图片描述

附代码

#include <math.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define PI 3.1415926static float angle(float ux, float uy, float vx, float vy) {   float res = (ux*vx + uy*vy)/sqrtf((ux*ux+uy*uy)*(vx*vx+vy*vy));res = MIN(MAX(res,-1),1);  //-1 <= res <= 1;float a ; if ((ux*vy - uy*vx) < 0)a = -acosf(res);elsea = acosf(res);return a;
}static int calcEllipse(float rx, float ry, float ph, int fa, int fs, float x1, float y1, float x2, float y2, float* pcx, float* pcy, float* pth, float* pdth) 
{if (!rx || !ry) return -1; rx = (rx > 0) ? rx : -rx;ry = (ry > 0) ? ry : -ry;float xp, yp; {   float tx = (x1 - x2) / 2;float ty = (y1 - y2) / 2;xp = cosf(ph)*tx + sinf(ph)*ty;yp = -sinf(ph)*tx + cosf(ph)*ty;float lambda = xp*xp/(rx*rx) + yp*yp/(ry*ry);if (lambda > 1) {lambda = sqrtf(lambda);rx = lambda*rx;ry = lambda*ry;}}float cx,cy;float th, dth;{float pr;{float tp = rx*rx*yp*yp + ry*ry*xp*xp;pr = sqrtf((rx*rx*ry*ry - tp)/tp);}float cxp,cyp;if (fa != fs) {cxp =  pr * rx * yp / ry;cyp = -pr * ry * xp / rx;} else {cxp = -pr * rx * yp / ry;cyp =  pr * ry * xp / rx;}cx = cosf(ph)*cxp - sinf(ph)*cyp + (x1+x2)/2;cy = sinf(ph)*cxp + cosf(ph)*cyp + (y1+y2)/2;th = angle(1, 0, (xp - cxp) / rx, (yp - cyp) / ry);dth = angle((xp-cxp)/rx,(yp-cyp)/ry,(-xp-cxp)/rx,(-yp-cyp)/ry);dth = fmod(dth,2*PI);}if ( fs==0 && dth > 0)dth -= 2*PI;if ( fs==1 && dth < 0)dth += 2*PI;*pcx = cx;*pcy = cy;*pth = th;*pdth = dth;return 0;
}
//  EFAULT pathname points outside your accessible address space
static int adrNotValid(void* p)
{int fd = open(p, 0, 0);int e = errno;if (fd == -1 && e == EFAULT)return 1;else if (fd != -1)close(fd);return 0;
}static int _bezierEllipse(float cx, float cy, float rx, float ry,float th, float sth, float eth,float* res)
{if(!res || adrNotValid(res) || adrNotValid(&res[5]))return -1;float x1 = cx + rx * cosf(th)*cosf(sth) - ry * sinf(th)*sinf(sth);float y1 = cy + rx * sinf(th)*cosf(sth) + ry * cosf(th)*sinf(sth);float x2 = cx + rx * cosf(th)*cosf(eth) - ry * sinf(th)*sinf(eth);float y2 = cy + rx * sinf(th)*cosf(eth) + ry * cosf(th)*sinf(eth);float dx1 = -1 * rx * cosf(th) * sinf(sth) - ry * sinf(th) * cosf(sth);float dy1 = -1 * rx * sinf(th) * sinf(sth) + ry * cosf(th) * cosf(sth);float dx2 = -1 * rx * cosf(th) * sinf(eth) - ry * sinf(th) * cosf(eth);float dy2 = -1 * rx * sinf(th) * sinf(eth) + ry * cosf(th) * cosf(eth);float tmp = tan((eth-sth)/2);float alpha = sinf(eth - sth)*(sqrtf(4+3*tmp*tmp)-1)/3;//   *res++ = x1;//   *res++ = y1;*res++ = x1 + alpha*dx1; // p1x*res++ = y1 + alpha*dy1; // p1y*res++ = x2 - alpha*dx2; // p2x*res++ = y2 - alpha*dy2; // p2y*res++ = x2;*res++ = y2;return 0;
}int bezierEllipse(float cx, float cy, float rx, float ry,float th, float sth, float eth, int n,float* res)
{if (n <= 0 || sth == eth) return -1;float step = (eth - sth)/n;float tmp = sth;for (int i = 0; i < n; i++) {int e = _bezierEllipse(cx, cy, rx, ry,th, tmp, tmp+step,res);if (e) return -1;tmp += step;res += 6;}return 0;
}int main()
{float rx = 50;float ry = 40;float phi = -120.0/180 * PI ;float x1 = 100;float y1 = 80;float x2 = 120;float y2 = 60;float cx,cy,th,dth;calcEllipse( rx, ry, phi, 1, 0, x1, y1, x2, y2,&cx,&cy,&th,&dth);printf("%f %f %f %f\n",cx,cy,th,dth);int dn = ceilf(((dth > 0)? dth : -dth)  * 4 / PI) ;if (dn < 1)return 0;int size = 2+6*dn;float* data = (float*)malloc(size*sizeof(float));data[0] = x1;data[1] = y1;bezierEllipse(cx, cy, rx, ry,phi, th, th+dth, dn,data+2);data[size-2] = x2;data[size-1] = y2;printf("M %f %f ",x1,y1);for(int i = 0; i < dn; i++) {printf(" C ");for(int j = 0; j < 6; j++)printf(" %f ",data[2+6*i+j]);}printf("\n");
}

拟合圆 椭圆 测试结果
在这里插入图片描述

参考 https://www.w3.org/TR/SVG/implnote.html
https://paperzz.com/doc/7611457/drawing-an-elliptical-arc-using-polylines–quadratic-or

这篇关于bezier曲线拟合椭圆弧线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/830591

相关文章

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

(4)SVG-path中的椭圆弧A(绝对)或a(相对)

1、概念 表示经过起始点(即上一条命令的结束点),到结束点之间画一段椭圆弧 2、7个参数 rx,ry,x-axis-rotation,large-arc-flag,sweep-flag,x,y (1)和(2)rx,ry rx:椭圆的x轴半径(即水平半径) ry:椭圆的y轴半径(即垂直半径) 这两个参数好理解,就是椭圆的两条对称轴半径,相等即为圆 也可以写比例,写比例时默认用符合条件

python实现椭圆曲线加密算法(ECC)

目录 椭圆曲线加密算法(ECC)简介ECC的数学基础椭圆曲线的定义ECC的基本操作 ECC加密和解密流程Python面向对象实现ECC加密和解密代码解释场景应用:安全通信总结 椭圆曲线加密算法(ECC)简介 椭圆曲线加密算法(Elliptic Curve Cryptography, ECC)是一种基于椭圆曲线数学结构的公钥加密算法。ECC以其较高的安全性和较小的密钥长度而闻名

2d椭圆拟合学习

算法来自论文《 Direct Least Square Fitting of Ellipses》 《NUMERICALLY STABLE DIRECT LEAST SQUARES FITTING OF ELLIPSES》 相关文章  论文阅读:·直接拟合椭圆 Direct Least Square Fitting of Ellipseshttps://zhuanlan.zhihu.com/p

Dxf文件中多段线弧线的计算

要计算弧形的参数(包括起始角度、跨度角度以及包围弧形的矩形),我们首先需要理解一些基础知识: 弧的半径和中心:弧是圆的一部分,因此我们首先要计算整个圆的半径和圆心。起始角度和跨度角度:弧的角度通常以度数表示,但在某些图形库中(如 Qt 的 drawArc 方法),需要以 1/16 度为单位来计算。 calArc 函数计算了圆的半径、圆心、矩形范围、起始角度和跨度角度。下面是对这些计算的详细解释

零知识证明-椭圆曲线(四)

前言 零知识证明(Zero—Knowledge Proof),是指一种密码学工具,允许互不信任的通信双方之间证明某个命题的有效性,同时不泄露任何额外信息 上章介绍了基础数字知识,这章主要讲 椭圆曲线 方程 2:椭圆曲线方程 y2+axy+by=x3+cx2+dx+e 式中,a、b、c、d、e均为实数,x和y在实数集上取值。 在加密领域一般采用如下简化后的数学形式: 有限域椭圆曲线 y2= x3+

OpenCV绘图函数(7)从一个椭圆定义中提取出多边形的顶点坐标函数ellipse2Poly()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 近似一个椭圆弧为一个多边形线。 函数 ellipse2Poly 计算近似指定椭圆弧的多边形线的顶点。它被 ellipse 函数所使用。如果 arcStart 大于 arcEnd,它们会被交换。 函数原型1 void cv::ellipse2

前端使用 Konva 实现可视化设计器(21)- 绘制图形(椭圆)

本章开始补充一些基础的图形绘制,比如绘制:直线、曲线、圆/椭形、矩形。这一章主要分享一下本示例是如何开始绘制一个图形的,并以绘制圆/椭形为实现目标。 请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了 Bug,欢迎来提 Issue 哟~ github源码 gitee源码 示例地址 接下来主要说说: UIGraph(图形)canvas2svg 打补丁拐点旋转修复 UI -

Bezier曲线曲面--拟合技术

Bezier曲线曲面–拟合应用 1.Bezier曲线 1.1.Bezier曲线的定义 给定一组控制点 P_0, P_1, …, P_n,其中 n 是曲线的阶数,Bezier曲线的参数方程可以表示为: B ( t ) = ∑ i = 0 n P i b i , n ( t ) , t ∈ [ 0 , 1 ] B(t) = \sum_{i=0}^{n} P_i b_{i,n}(t), \qua

关于椭圆的方程(有Python画的动图)

关于椭圆的方程(有Python画的动图) flyfish 几何定义 椭圆是平面上所有到两个固定点(焦点)的距离之和为常数的点的集合。这两个固定点叫做焦点。 解析几何描述 设椭圆的两个焦点为 F 1 F_1 F1​ 和 F 2 F_2 F2​,焦距(两焦点之间的距离的一半)为 c c c,长轴的半长轴为 a a a,短轴的半短轴为 b b b,椭圆上任意一点到这两个焦点的距离之