1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense>
using namespace std; using namespace Eigen;
struct Point { double x, y; };
struct Circle { double a, b, r; };
double residual(const Circle &circle, const Point &point) { return sqrt(pow(point.x - circle.a, 2) + pow(point.y - circle.b, 2)) - circle.r; }
Circle fitCircle(const vector<Point> &points, Circle initial_guess, int max_iterations = 100, double tolerance = 1e-6) { Circle circle = initial_guess;
for (int iter = 0; iter < max_iterations; ++iter) { int n = points.size(); VectorXd r(n); MatrixXd J(n, 3);
for (int i = 0; i < n; ++i) { double dx = points[i].x - circle.a; double dy = points[i].y - circle.b; double dist = sqrt(dx * dx + dy * dy);
r(i) = dist - circle.r;
J(i, 0) = -dx / dist; J(i, 1) = -dy / dist; J(i, 2) = -1.0; }
VectorXd delta = (J.transpose() * J).ldlt().solve(-J.transpose() * r);
circle.a += delta(0); circle.b += delta(1); circle.r += delta(2);
if (delta.norm() < tolerance) break; }
return circle; }
int main() { vector<Point> points = { {1, 2}, {2, 3}, {3, 4}, {4, 5} }; Circle initial_guess = {0, 0, 1};
Circle fitted_circle = fitCircle(points, initial_guess);
cout << "Fitted circle: center=(" << fitted_circle.a << ", " << fitted_circle.b << "), radius=" << fitted_circle.r << endl;
return 0; }
|