fit_circle {lidR} | R Documentation |
Fits 2D Circles on a Point Cloud
Description
Fits a 2D horizontally-aligned circle to a set of 3D points. The method uses RANSAC-based fitting for robust estimation. The function returns a list with the circle parameters and additional data to help determine whether the points form a circular shape. While it is always possible to fit a circle to any dataset, the additional information assists in evaluating if the data genuinely represent a circular pattern. The root mean square error (RMSE) may not always be a reliable metric for assessing the quality of the fit due to non-circular elements (such as branches) that can arbitrarily increase the RMSE of an otherwise well-fitted circle, as shown in the example below. Therefore, the function also returns the angular range of the data, which indicates the spread of the inlier points: 360 degrees suggests a full circle, 180 degrees indicates a half-circle, or a smaller range may suggest a partial arc.
Usage
fit_circle(points, num_iterations = 100, inlier_threshold = 0.01)
Arguments
points |
A LAS object representing a clustered slice, or an nx3 matrix of point coordinates. |
num_iterations |
The number of iterations for the RANSAC fitting algorithm. |
inlier_threshold |
A threshold value; points are considered inliers if their residuals are below this value. |
Value
A list containing the circle parameters and additional information for determining whether the data fit a circular shape:
-
center_x
,center_y
,radius
: parameters of the fitted circle. -
z
: average elevation of the circle. -
rmse
: root mean square error between the circle and all points. -
covered_arc_degree
: angular sector covered by inlier points. -
percentage_inlier
: percentage of points that are inliers -
percentage_inside
: percentage of points inside the circle -
inliers
: IDs of the inlier points.
Examples
LASfile <- system.file("extdata", "dbh.laz", package="lidR")
las <- readTLS(LASfile, select = "xyz")
xyz = sf::st_coordinates(las)
circle = fit_circle(xyz)
plot(xyz, asp = 1, pch = 19, cex = 0.1)
symbols(circle$center_x, circle$center_y, circles = circle$radius,
add = TRUE, fg = "red", inches = FALSE)
trunk = las[circle$inliers]
# Fitting a half-circle
half = xyz[xyz[,1] > 101.45,]
circle = fit_circle(half)
plot(half, asp = 1, pch = 19, cex = 0.1)
symbols(circle$center_x, circle$center_y, circles = circle$radius,
add = TRUE, fg = "red", inches = FALSE)
circle$covered_arc_degree