Данные напоминают цилиндрическую форму с отсоединенными частями внутри. между, что на данном этапе можно игнорировать. Эти данные состоят из компонентов X, Y и Z.

Сначала я подумал, что было бы лучше взять поперечное сечение данных и найти лучший круг, подходящий для него, а затем применить его ко всем данным, чтобы получить много кругов .
Сначала мне удалось получить аппроксимацию кривой после замены осей X и Z, чтобы сделать данные явными (спасибо jlandercy за ответ на мой предыдущий вопрос (описание точек данных с помощью arc- Затем извлекли круг из точки, где наклон равен 0. Эта идея исходит из того факта, что круг должен помещаться под углом 90 градусов между горизонтальной и вертикальной линиями, как показано на следующем рисунке. изображение:

.
Чтобы объяснить это более подробно, Я нашел точку на кривой данных поперечного сечения, где наклон равен 0, и нашел другую точку, где наклон равен бесконечности. Но поскольку на кривой нет точки, где наклон был бы бесконечен, я предположил, что идеальный круг не может разместиться вдоль всей кривой, но наиболее подходящий круг можно нарисовать в точке, где наклон равен 0. Итак, я нашел координаты точки, наклон которой равен 0, и сравнили ее с самой низкой точкой данных поперечного сечения. Я использовал их координаты, чтобы найти центр круга, и использовал разницу компонента X между точкой наклона 0 и центром, чтобы найти радиус. В результате мне удалось нарисовать круг, который, по-видимому, лучше всего соответствует кривой на поперечном сечении, как показано желтым цветом на рисунке ниже.
В то время я игнорировал компоненты Y. , поскольку я обнаружил, что их дисперсия и стандартное отклонение были очень низкими по сравнению с дисперсией и стандартным отклонением компонентов X и Z, а это означает, что они не влияют на мой анализ.

Теперь мой план пытается применить его ко всему все данные, чтобы я мог создавать круги для каждого сечения. Примерно так, как показано ниже.

Конечная цель — соединить центры этих кругов на каждом сечении данных, чтобы получить непрямую линию, что, я думаю, не будет слишком сложным, если я смогу получить круги на всех сечениях данных. поперечные сечения.
Надеюсь, то, чего я пытаюсь достичь, понятно. На данный момент я просто понятия не имею, как применить метод поперечного сечения к исходным данным. Я подумывал о том, чтобы использовать цикл for, чтобы применить его ко всем данным, но не совсем представлял, как для него указать цикл. Я пытался получить помощь от Chat-GPT, но это мне не помогло.
Я также пробовал другие методы поиска определенной линии облака точек, такие как комбинация Делане. Триангуляция и тесселяция Вороного, как предложено в другом посте «Подгонка кривой-сплайна к 3D-облаку точек». Но мне это не удалось.
Если кто-нибудь может дать мне подсказку или совет, я был бы признателен.
Исходные данные слишком большой, поэтому я добавляю в свой OneDrive ссылку: Исходные данные
Вот фрагмент моего кода, показывающий, как я подошел к идее подгонки круга в поперечном сечении.
Код: Выделить всё
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Load the point cloud data
data = pd.read_csv('data/selected_2.csv')
points = data.to_numpy()
x = points[:, 0]
y = points[:, 1]
z = points[:, 2]
# Calculate polynomial
a = np.polyfit(z, x, 7)
f_poly = np.poly1d(a)
# Find new x and y data along the curve
z_new = np.linspace(z[0], z[-1], 50)
x_new = f_poly(z_new)
data_new = np.vstack((z_new, x_new)).T
# Define the derivative function
def FindingDerivatives(data_new):
slopes = []
for i in range(len(data_new) - 1):
z1, x1 = data_new[i]
z2, x2 = data_new[i + 1]
slope = (x2 - x1) / (z2 - z1)
slopes.append((z1, slope))
return slopes
# Define the function to find perpendicular line slopes
def FindingPerpendicular(slopes):
perpendicular = []
for z1, slope in slopes:
if slope != 0:
inverse = -1 / slope # Perpendicular line is the inverse of the original slope
else:
inverse = float('inf') # Perpendicular to a horizontal line is a vertical line
perpendicular.append((z1, inverse))
return perpendicular
# Find the maximum slope element
def FindMinMaxSlopeElement(slopes):
target_slope_elements = []
max_slope_elements = 0
min_slope_elements = 0
max_slope = max(slopes)[1]
min_slope = min(slopes)[1]
print(max_slope, min_slope)
for i in range(len(slopes)):
if slopes[i][1] == min_slope:
max_slope_elements = slopes[i]
if slopes[i][1] == max_slope:
min_slope_elements = slopes[i]
target_slope_elements.append(min_slope_elements)
target_slope_elements.append(max_slope_elements)
return target_slope_elements
# Find the corresponding coordinates to the maximum slope element
def FindCorrespondingCoordinates(target_slope_elements, data):
min_coordinates = []
max_coordinates = []
target_coordinates = []
for i in range(len(data)):
if data[:, 0][i] == target_slope_elements[0][0]:
min_coordinates.append(data[:, 0][i])
min_coordinates.append(data[:, 1][i])
if data[:, 0][i] == target_slope_elements[1][0]:
max_coordinates.append(data[:, 0][i])
max_coordinates.append(data[:, 1][i])
print(min_coordinates)
print(max_coordinates)
target_coordinates.append(min_coordinates)
target_coordinates.append(max_coordinates)
return target_coordinates
# Find the circle based on the coordinate values corresponding to the maximum and minimum slopes
def FindCircle(target_coordinates):
circle_info = []
center_z = target_coordinates[0][1]
center_x = target_coordinates[1][0]
center = [center_z, center_x]
radius = target_coordinates[0][0] - target_coordinates[1][0]
print(center, radius)
circle_info.append(radius)
circle_info.append(center)
return circle_info
# Draw the circle
def CircleDraw(circle, test_data, z_new, x_new):
radius = circle[0]
fig, ax = plt.subplots()
ax.scatter(test_data[:, 1], test_data[:, 0])
ax.plot(z_new, x_new, 'y')
cir = plt.Circle((circle[1][0], circle[1][1]), radius, color='r',fill=False)
center_label = f"center: \n {round(circle[1][0], 2), round(circle[1][1], 2)}"
plt.annotate(center_label, xy=(circle[1][0], circle[1][1]), ha='center')
ax.set_aspect('equal', adjustable='datalim')
ax.add_patch(cir)
ax.set_xlabel('Z Data') # X axis data label
ax.set_ylabel('X Data') # Y axis data label
plt.show()
# Organize the test data (only taking 'X' and 'Z' coordinates of the original data)
test_data = points[:, [0, 2]]
# Find the slope of the original data
slopes = FindingDerivatives(test_data)
# Find perpendicular lines of the original data
perpendicular = FindingPerpendicular(slopes)
# Find minimum and maximum slope elements
target_slope_elements = FindMinMaxSlopeElement(slopes)
print("Target Slopes", target_slope_elements)
# Find the target coordinates
target_coordinates = FindCorrespondingCoordinates(target_slope_elements, test_data)
print("Target Coordinates: ", target_coordinates)
# Find the circle information
circle = FindCircle(target_coordinates)
print("radius: %s center: %s" % (circle[0], circle[1]))
# Call the circle function
CircleDraw(circle, test_data, z_new, x_new)
Код: Выделить всё
# Here is the cross-section of the data
# ('Y' components are not really used as I decided that they don't really affect my analysis)
X,Y,Z
1702113.3399999738,2434223.5100000203,9080.16
1702132.699999988,2434227.2700000107,9079.86
1702172.7199999988,2434233.629999995,9106.22
1702153.0400000215,2434230.4699999997,9087.98
1702143.6899999976,2434227.5699999933,9083.15
1702167.079999983,2434224.6899999976,9100.11
1702159.8799999952,2434236.3600000143,9093.52
1702177.9900000098,2434225.169999987,9113.97
1702192.0399999917,2434220.0899999742,9155.37
1702186.7199999988,2434228.7599999905,9128.54
1702191.330000013,2434221.2299999893,9174.77
1702182.9099999962,2434234.8899999857,9120.3
1702182.580000013,2434217.7899999917,9121.94
1702192.1200000048,2434219.9599999785,9164.910000000002
1702189.5399999917,2434224.2199999997,9137.12
1702191.229999989,2434221.3899999857,9146.08
1702188.9300000072,2434225.100000024,9185.21
1702183.5,2434216.300000012,9198.22
1702175.5,2434229.150000006,9220.28
1702178.099999994,2434224.9799999893,9209.75
1702188.080000013,2434226.4600000083,9223.87
1702184.669999987,2434231.9600000083,9196.33
1702214.9900000098,2434218.3599999845,9220.34
Большое спасибо!
Подробнее здесь: https://stackoverflow.com/questions/787 ... on-3d-data