← Назад к вопросам
Как построить параболу между точками из разных пространств, если допускается различный коэффициент параболы для каждой линии?
3.0 Senior🔥 51 комментариев
#Архитектура и паттерны#Другое
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Построение парабол между точками из разных пространств
Эта задача относится к интерполяции и аппроксимации кривых в многомерных пространствах. Рассмотрю несколько подходов для построения парабол с индивидуальными коэффициентами.
1. Парабола в одномерном пространстве
Если у нас есть точки (x1, y1), (x2, y2), (x3, y3), мы можем построить параболу вида y = ax² + bx + c:
import numpy as np
from scipy.interpolate import lagrange, CubicSpline
import matplotlib.pyplot as plt
# Точки
points = np.array([(1, 2), (2, 4), (3, 8)])
x = points[:, 0]
y = points[:, 1]
# Полиномиальная интерполяция (степень 2 = парабола)
parabola = np.polyfit(x, y, deg=2)
print(f'Коэффициенты параболы (a, b, c): {parabola}')
# a, b, c = parabola
# y = ax² + bx + c
# Вычисление значений на параболе
x_new = np.linspace(1, 3, 100)
y_new = np.polyval(parabola, x_new)
plt.plot(x, y, 'ro', label='Исходные точки')
plt.plot(x_new, y_new, 'b-', label='Парабола')
plt.legend()
plt.show()
2. Парабола в многомерном пространстве (линии в 3D)
Если у нас есть линии в 3D пространстве (или любом другом), мы можем построить параболу через каждую координату отдельно:
import numpy as np
class ParabolaInterpolator:
"""Интерполирует линию параболами в многомерном пространстве"""
def __init__(self, points):
"""
Args:
points: массив формы (n_points, n_dims) - точки в многомерном пространстве
"""
self.points = np.array(points)
self.n_points = len(points)
self.n_dims = points.shape[1]
self.t = np.linspace(0, 1, self.n_points) # параметр от 0 до 1
self.parabolas = [] # коэффициенты парабол для каждой координаты
self._fit_parabolas()
def _fit_parabolas(self):
"""Подгоняет параболу для каждого измерения"""
for dim in range(self.n_dims):
# Берём координату для текущего измерения
y = self.points[:, dim]
# Подгоняем параболу y = at² + bt + c
coeff = np.polyfit(self.t, y, deg=2)
self.parabolas.append(coeff)
def evaluate(self, t_new):
"""Вычисляет точки на параболах для новых значений параметра
Args:
t_new: параметр (или массив параметров) от 0 до 1
Returns:
Точки (или массив точек) в многомерном пространстве
"""
result = []
for coeff in self.parabolas:
y = np.polyval(coeff, t_new)
result.append(y)
return np.array(result).T if np.isscalar(t_new) else np.array(result).T
# Пример: линия в 3D пространстве
points_3d = np.array([
[0, 0, 0],
[1, 2, 1],
[2, 2, 4]
])
interp = ParabolaInterpolator(points_3d)
t_new = np.linspace(0, 1, 50)
interpolated = interp.evaluate(t_new)
print(f'Исходные точки:\n{points_3d}')
print(f'Коэффициенты парабол:\n{interp.parabolas}')
print(f'Первая интерполированная точка: {interpolated[0]}')
3. Разные коэффициенты для разных линий
Если у нас есть несколько линий и для каждой нужен свой коэффициент параболы:
class AdaptiveParabolaInterpolator:
"""Интерполирует несколько линий с индивидуальными коэффициентами"""
def __init__(self, lines, coeff_function=None):
"""
Args:
lines: список линий, каждая - массив точек
coeff_function: функция для выбора коэффициента k для линии
По умолчанию k зависит от длины линии
"""
self.lines = [np.array(line) for line in lines]
self.interpolators = []
self.coefficients = []
if coeff_function is None:
# По умолчанию: k = 1 / длину линии
coeff_function = lambda line: 1.0 / np.linalg.norm(
line[-1] - line[0] + 1e-8
)
self._fit_interpolators(coeff_function)
def _fit_interpolators(self, coeff_function):
"""Подгоняет параболы для каждой линии"""
for line in self.lines:
coeff = coeff_function(line)
self.coefficients.append(coeff)
# Параметризуем линию
t = np.linspace(0, 1, len(line))
# Подгоняем параболу с масштабированием
parabolas = []
for dim in range(line.shape[1]):
y = line[:, dim]
# Применяем коэффициент
y_scaled = y * coeff
poly = np.polyfit(t, y_scaled, deg=2)
parabolas.append(poly)
self.interpolators.append(parabolas)
def evaluate_line(self, line_idx, t_new):
"""Вычисляет точки на параболе для конкретной линии"""
parabolas = self.interpolators[line_idx]
coeff = self.coefficients[line_idx]
result = []
for poly in parabolas:
y = np.polyval(poly, t_new) / coeff # Убираем масштабирование
result.append(y)
return np.array(result).T if np.isscalar(t_new) else np.array(result).T
# Пример
lines = [
np.array([[0, 0], [1, 1], [2, 0]]), # Короткая линия
np.array([[0, 0], [5, 2], [10, 4]]) # Длинная линия
]
adaptive = AdaptiveParabolaInterpolator(lines)
print(f'Коэффициент для линии 0: {adaptive.coefficients[0]:.4f}')
print(f'Коэффициент для линии 1: {adaptive.coefficients[1]:.4f}')
# Интерполируем
t_new = np.linspace(0, 1, 20)
for i, line in enumerate(lines):
interpolated = adaptive.evaluate_line(i, t_new)
print(f'\nЛиния {i}:')
print(f'Первая интерполированная точка: {interpolated[0]}')
4. Кубический сплайн с адаптивностью
Для более гладких кривых используем кубические сплайны:
from scipy.interpolate import CubicSpline
class AdaptiveSplineInterpolator:
"""Интерполирует линии кубическими сплайнами с индивидуальными параметрами"""
def __init__(self, lines, boundary_type='natural', bc_type='natural'):
"""
Args:
lines: список линий
bc_type: тип граничных условий
"""
self.lines = [np.array(line) for line in lines]
self.splines = []
self.t_params = []
for line in self.lines:
# Параметризуем линию кумулятивной длиной
distances = [0]
for i in range(1, len(line)):
dist = np.linalg.norm(line[i] - line[i-1])
distances.append(distances[-1] + dist)
t = np.array(distances) / (distances[-1] + 1e-8)
self.t_params.append(t)
# Строим сплайны для каждого измерения
splines_dim = []
for dim in range(line.shape[1]):
spl = CubicSpline(t, line[:, dim], bc_type=bc_type)
splines_dim.append(spl)
self.splines.append(splines_dim)
def evaluate_line(self, line_idx, t_new):
"""Вычисляет точки на сплайне"""
splines_dim = self.splines[line_idx]
result = []
for spl in splines_dim:
y = spl(t_new)
result.append(y)
return np.array(result).T if np.isscalar(t_new) else np.array(result).T
# Использование
lines = [
np.array([[0, 0, 0], [1, 2, 1], [2, 2, 0]]),
np.array([[0, 0], [3, 5], [5, 3], [8, 1]])
]
interp = AdaptiveSplineInterpolator(lines)
for i in range(len(lines)):
t_new = np.linspace(0, 1, 30)
result = interp.evaluate_line(i, t_new)
print(f'Линия {i}: {len(result)} интерполированных точек')
5. Матричный подход для параболы через 3 точки
def fit_parabola_3d(p1, p2, p3):
"""
Строит параболу через три точки в 3D пространстве
Парабола параметризуется как: P(t) = p1 + (p2-p1)*t + (p1 - 2*p2 + p3)*t²
"""
p1 = np.array(p1)
p2 = np.array(p2)
p3 = np.array(p3)
# Квадратичная параметризация
a = p1 - 2*p2 + p3 # коэффициент при t²
b = p2 - p1 # коэффициент при t
c = p1 # коэффициент при t⁰
def parabola(t):
t = np.asarray(t)
return c + b*t[:, None] + a*t[:, None]**2
return parabola, (a, b, c)
# Пример
p1 = np.array([0, 0, 0])
p2 = np.array([1, 2, 1])
p3 = np.array([2, 2, 4])
parabola, coeffs = fit_parabola_3d(p1, p2, p3)
# Вычисляем точки на параболе
t_new = np.linspace(0, 1, 50)
points = parabola(t_new)
print(f'Форма результата: {points.shape}')
print(f'Первая точка: {points[0]}')
print(f'Последняя точка: {points[-1]}')
Мои рекомендации
- Для простых случаев: используй numpy.polyfit() — быстро и просто
- Для многомерного пространства: параметризуй линию и подгоняй параболу для каждого измерения
- Для гладких кривых: используй CubicSpline вместо парабол
- Для сложных коэффициентов: определи метрику (длину линии, кривизну) и используй её для выбора коэффициента
- Проверяй граничные условия: убедись что парабола проходит через исходные точки