← Назад к вопросам

Как построить параболу между точками из разных пространств, если допускается различный коэффициент параболы для каждой линии?

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 вместо парабол
  • Для сложных коэффициентов: определи метрику (длину линии, кривизну) и используй её для выбора коэффициента
  • Проверяй граничные условия: убедись что парабола проходит через исходные точки