IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 最小二乘法圆拟合(附完整代码) -> 正文阅读

[数据结构与算法]最小二乘法圆拟合(附完整代码)

一、2D圆弧拟合

1、不经过给定起点与终点

??平面圆的一般方程为:
x 2 + y 2 + a x + b y + c = 0 (1) x^2 + y^2 + ax + by +c = 0\tag 1 x2+y2+ax+by+c=0(1)
??其中, a , b , c ∈ R a,b,c\in R a,b,cR
??式(1)配方,可以得到:
( x + a / 2 ) 2 + ( x + b / 2 ) 2 = a 2 / 4 + b 2 / 4 ? c (2) (x + a/2)^2 + (x + b/2)^2 = a^2/4 + b^2/4 - c \tag 2 (x+a/2)2+(x+b/2)2=a2/4+b2/4?c(2)

??对于给定的一系列二维数据 ( x i , y i ) , i = 0 , . . . , n (x_i,y_i),i=0,...,n (xi?,yi?),i=0,...,n,根据式(1)可以列出 n + 1 n+1 n+1个线性方程,然后可以采用最小二乘法求解,非常简单有效。

2、精确经过给定起点与终点

??有时候我们需要约束圆弧精确经过给定起点与终点,设起点坐标为 ( x 0 , y 0 ) (x_0,y_0) (x0?,y0?),终点坐标为 ( x n , y n ) (x_n,y_n) (xn?,yn?),则有约束等式:
{ x 0 2 + y 0 2 + a x 0 + b y 0 + c = 0 x n 2 + y n 2 + a x n + b y n + c = 0 (3) \begin{cases} x_0^2 + y_0^2 + ax_0 + by_0 +c = 0 \\ x_n^2 + y_n^2 + ax_n + by_n +c = 0 \\ \tag 3 \end{cases} {x02?+y02?+ax0?+by0?+c=0xn2?+yn2?+axn?+byn?+c=0?(3)
??(1)若起点与终点坐标重合,则式(3)退化为一个约束等式,将参数 c c c的表达式代入到式(1),利用最小二乘法求解参数 a , b a,b a,b,再计算参数 c c c
??(2)若 x 0 ≠ x n x_0\ne x_n x0??=xn?,根据式(3)解出参数 a , c a,c a,c的表达式,然后代入到式(1),利用最小二乘法求解参数 b b b,再计算参数 a , c a,c a,c
??(3)若 y 0 ≠ y n y_0\ne y_n y0??=yn?,根据式(3)解出参数 b , c b,c b,c的表达式,然后代入到式(1),利用最小二乘法求解参数 a a a,再计算参数 b , c b,c b,c

??circle_fitting_2D.m

function [ center, R, fittingError ] = circle_fitting_2D( points, pointCount, crossStartAndEndPointFlag )
%{
Function: circle_fitting_2D
Description: 2D圆弧拟合
Input: 二维点points, 点个数pointCount, 是否经过起点/终点标志位crossStartAndEndPointFlag
Output: 圆心center, 半径R, 拟合误差fittingError
Author: Marc Pony(marc_pony@163.com)
圆的方程:x^2 + y^2 + a*x + b*y +c = 0  -> (x + a/2)^2 + (x + b/2)^2 = a^2/4 + b^2/4 - c
%}
if crossStartAndEndPointFlag == 0
    x = points(:, 1);
    y = points(:, 2);
    A = [x, y, ones(size(x))];
    B = -x.^2 - y.^2;
    temp = A \ B;
    
    a = temp(1);
    b = temp(2);
    c = temp(3);
else
    x0 = points(1, 1);
    y0 = points(1, 2);
    xn = points(pointCount, 1);
    yn = points(pointCount, 2);
    x = points(2 : pointCount - 1, 1);
    y = points(2 : pointCount - 1, 2);
    EPS = 1.0e-4;
    
    if abs(x0 - xn) < EPS && abs(y0 - yn) < EPS %起点与终点重合
        A = [x - x0, y - y0];
        B = x0^2 + y0^2 - x.^2 - y.^2;
        temp = A \ B;
        a = temp(1);
        b = temp(2);
        c = -x0^2 - y0^2 - a * x0 - b * y0;
    else
        if abs(x0 - xn) > abs(y0 - yn)
            A = x * (yn - y0) / (x0 - xn) + y - (x0 * yn - xn * y0) / (x0 - xn);
            B = -x.^2 - y.^2 - x * (xn^2 + yn^2 - x0^2 - y0^2) / (x0 - xn) + ((xn^2 + yn^2) * x0 - (x0^2 + y0^2) * xn) / (x0 - xn);
            b = A \ B;
            P = -x0^2 - y0^2 - b * y0;
            Q = -xn^2 - yn^2 - b * yn;
            a = (P - Q) / (x0 - xn);
            c = -(P * xn - Q * x0) / (x0 - xn);
        else
            A = x * (xn - x0) / (y0 - yn) + y - (y0 * xn - yn * x0) / (y0 - yn);
            B = -x.^2 - y.^2 - x * (yn^2 + xn^2 - y0^2 - x0^2) / (y0 - yn) + ((yn^2 + xn^2) * y0 - (y0^2 + x0^2) * yn) / (y0 - yn);
            a = A \ B;
            P = -y0^2 - x0^2 - a * x0;
            Q = -yn^2 - xn^2 - a * xn;
            b = (P - Q) / (y0 - yn);
            c = -(P * yn - Q * y0) / (y0 - yn);
        end
    end
end

R = sqrt(a^2 / 4 + b^2 / 4 - c);
center(1) = -a / 2;
center(2) = -b / 2;
fittingError = sqrt((points(:, 1) - center(1)).^2 + (points(:, 2) - center(2)).^2) - R;

end

??test_circle_fitting_2D.m

clc
clear
close all

%% 绘参考圆
figure
axis([0 100 0 100])
theta = linspace(0, 2*pi, 1000);
r = 30;
x = 50 + r*cos(theta);
y = 50 + r*sin(theta);
plot(x,y,'g--')
hold on
axis equal

%% 左键点击取点,按回车键退出
pos = ginput();
%pos = [pos;pos(1,1), pos(1,2)];  %起点与终点重合
pointCount = size(pos, 1);
plot(pos(1, 1), pos(1, 2), 'k+')
plot(pos(pointCount, 1), pos(pointCount, 2), 'k+')
plot(pos(2:pointCount-1, 1), pos(2:pointCount-1, 2), 'o')

%% 圆最小二乘拟合
crossStartAndEndPointFlag = 1; %0:不经过给定起点与终点;  1:精确经过给定起点与终点
[ center, R, fittingError ] = circle_fitting_2D( pos, pointCount, crossStartAndEndPointFlag )

x = center(1) + R * cos(theta);
y = center(2) + R * sin(theta);
plot(x, y, 'b')                   
plot(center(1), center(2), 'b+')
plot(center(1), center(2), 'bo')

在这里插入图片描述

二、3D圆弧拟合

?? 3D圆弧拟合可以分解两个问题:
?? (1)三维点的球面拟合(见博文:最小二乘法球面拟合(附完整代码))
?? (2)平面拟合
??球面拟合后,球心便为3D圆弧的圆心,平面拟合则可以得到3D圆弧所在平面的法向量,3D圆弧的方程便确定。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 12:17:23  更:2021-12-05 12:19:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:25:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码