Skip to content

Commit 6df67c0

Browse files
committed
Add a new implementation of fit circle
1 parent da32c9d commit 6df67c0

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/py_eddy_tracker/poly.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,48 @@ def fit_circle(x, y):
354354
return x0, y0, radius, err
355355

356356

357+
@njit(cache=True)
358+
def fit_circle_(x, y):
359+
"""
360+
From a polygon, function will fit a circle.
361+
362+
Must be call with local coordinates (in m, to get a radius in m).
363+
364+
.. math:: (x_i - x_0)^2 + (y_i - y_0)^2 = r^2
365+
.. math:: x_i^2 - 2 x_i x_0 + x_0^2 + y_i^2 - 2 y_i y_0 + y_0^2 = r^2
366+
.. math:: 2 x_0 x_i + 2 y_0 y_i + r^2 - x_0^2 - y_0^2 = x_i^2 + y_i^2
367+
368+
we get this linear equation
369+
370+
.. math:: a X + b Y + c = Z
371+
372+
where :
373+
374+
.. math:: a = 2 x_0 , b = 2 y_0 , c = r^2 - x_0^2 - y_0^2
375+
.. math:: X = x_i , Y = y_i , Z = x_i^2 + y_i^2
376+
377+
Solutions:
378+
379+
.. math:: x_0 = a / 2 , y_0 = b / 2 , r = \\sqrt{c + x_0^2 + y_0^2}
380+
381+
382+
:param array x: x of polygon
383+
:param array y: y of polygon
384+
:return: x0, y0, radius, shape_error
385+
:rtype: (float,float,float,float)
386+
"""
387+
datas = ones((x.shape[0] - 1, 3))
388+
# we skip first position which are the same than the last
389+
datas[:, 0] = x[1:]
390+
datas[:, 1] = y[1:]
391+
# Linear regression
392+
(a, b, c), _, _, _ = lstsq(datas, x[1:] ** 2 + y[1:] ** 2)
393+
x0, y0 = a / 2.0, b / 2.0
394+
radius = (c + x0 ** 2 + y0 ** 2) ** 0.5
395+
err = shape_error(x, y, x0, y0, radius)
396+
return x0, y0, radius, err
397+
398+
357399
@njit(cache=True, fastmath=True)
358400
def shape_error(x, y, x0, y0, r):
359401
"""

tests/test_poly.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ def test_fit_circle():
1515
assert x0 == approx(2.5, rel=1e-10)
1616
assert y0 == approx(-9.5, rel=1e-10)
1717
assert r == approx(2 ** 0.5 / 2, rel=1e-10)
18-
assert err == approx((r ** 2 * pi - 1) / (r ** 2 * pi) * 100, rel=1e-10)
18+
assert err == approx((1 - 2 / pi) * 100, rel=1e-10)

0 commit comments

Comments
 (0)