В компьютерной графике , то центростремительный Катмуллы Ром сплайн представляет собой варианты формы Катмулл-Rom сплайна , первоначально сформулирована Кэтмеллами и Рафаэль Rom , [1] , которые могут быть оценены с использованием рекурсивного алгоритма , предложенный Барри и Голдманом. [2] Это тип интерполирующего сплайна (кривая, проходящая через контрольные точки), определяемых четырьмя контрольными точками., с кривой, построенной только из к .
Определение
Позволять обозначают точку. Для сегмента кривой определяется точками и последовательность узлов центростремительный шлиц Катмулла – Рома может быть получен с помощью:
где
а также
в котором варьируется от 0 до 1 для параметризации узла, и с участием . Для центростремительного сплайна Катмулла – Рома значение является . Когда, полученная кривая представляет собой стандартный однородный сплайн Катмалла – Рома ; когда, произведение представляет собой хордовый сплайн Катмулла – Рома .
Подключение в сплайн-уравнения а также показывает, что значение сплайновой кривой при является . Аналогично подставляя в сплайновые уравнения показывает, что в . Это верно независимо от значения поскольку уравнение для не требуется для расчета стоимости в точках а также .
Расширение до трехмерных точек просто достигается путем рассмотрения обычная 3D-точка а также
Преимущества
Центростремительный сплайн Катмулла-Рома обладает несколькими желательными математическими свойствами по сравнению с исходной формулой и другими типами формулировки Катмулла-Рома. [3] Во-первых, он не будет образовывать петлю или самопересечение внутри сегмента кривой. Во- вторых, параболическая никогда не будет происходить в пределах сегмента кривой. В-третьих, более пристально следует за контрольными точками. [ расплывчато ]
Другое использование
В компьютерном зрении центростремительный сплайн Катмулла-Рома использовался для создания активной модели сегментации. Метод получил название активной сплайн-модели . [4] Модель разработана на основе модели активной формы , но использует центростремительный сплайн Катмулла-Рома для соединения двух последовательных точек (в модели активной формы используется простая прямая линия), так что общее количество точек, необходимых для изображения формы, составляет меньше. Использование центростремительного сплайна Катмулла-Рома значительно упрощает обучение модели формы и позволяет лучше редактировать контур после сегментации.
Пример кода на Python
Ниже представлена реализация сплайна Катмулла – Рома в Python, которая создает график, показанный ниже.
import numpy import matplotlib.pyplot as pltdef CatmullRomSpline ( P0 , P1 , P2 , P3 , nPoints = 100 ): "" " P0, P1, P2 и P3 должны быть (x, y) парами точек, которые определяют сплайн Катмулла-Рома. nPoints - количество точек для включения в этот сегмент кривой. "" " # Преобразуйте точки в numpy, чтобы мы могли выполнять умножение массивов P0 , P1 , P2 , P3 = map ( numpy . array , [ P0 , P1 , P2 , P3 ]) # Параметрическая константа: 0,5 для центростремительного шлица, 0,0 для равномерного шлица, 1,0 для хордового шлица. alpha = 0.5 # Предварительно умноженная константа мощности для следующей функции tj (). alpha = alpha / 2 def tj ( ti , Pi , Pj ): xi , yi = Pi xj , yj = Pj return (( xj - xi ) ** 2 + ( yj - yi ) ** 2 ) ** альфа + ti # Вычислить t0 до t4 t0 = 0 t1 = tj ( t0 , P0 , P1 ) t2 = tj ( t1 , P1 , P2 ) t3 = tj ( t2 , P2 , P3 ) # Вычислять только точки между P1 и P2 t = numpy . linspace ( t1 , t2 , nPoints ) # Измените форму так, чтобы мы могли умножить на точки от P0 до P3 # и получить балл за каждое значение t. т = т . reshape ( len ( t ), 1 ) print ( t ) A1 = ( t1 - t ) / ( t1 - t0 ) * P0 + ( t - t0 ) / ( t1 - t0 ) * P1 A2 = ( t2 - t ) / ( t2 - t1 ) * P1 + ( t - t1 ) / ( t2 - t1 ) * P2 A3 = ( t3 - t ) / ( t3 - t2 ) * P2 + ( t - t2 ) / ( t3 - t2 ) * P3 print ( A1 ) print ( A2 ) print ( A3 ) B1 = ( t2 - t ) / ( t2 - t0 ) * A1 + ( t - t0 ) / ( t2 - t0 ) * A2 B2 = ( t3 - t ) / ( t3 - t1 ) * A2 + ( t - t1 ) / ( t3 - t1 ) * A3 C = ( t2 - t ) / ( t2 - t1 ) * B1 + ( t - t1 ) / ( t2 - t1 ) * B2 вернуть Cdef CatmullRomChain ( P ): "" " Вычислить Catmull – Rom для цепочки точек и получить комбинированную кривую. " "" sz = len ( P ) # Кривая C будет содержать массив точек (x, y). С = [] для I в диапазоне ( SZ - 3 ): с = CatmullRomSpline ( Р [ я ], Р [ я + 1 ], Р [ я + 2 ], Р [ я + 3 ]) С . продлить ( c ) вернуть C# Определите набор точек, через которые должна пройти кривая. Points = [[ 0 , 1.5 ], [ 2 , 2 ], [ 3 , 1 ], [ 4 , 0.5 ], [ 5 , 1 ], [ 6 , 2 ], [ 7 , 3 ]]# Вычислить сплайны Catmull-Rom через точки c = CatmullRomChain ( Points )# Преобразовать точки кривой Катмулла-Рома в массивы x и y и построить график x , y = zip ( * c ) plt . сюжет ( x , y )# Постройте контрольные точки px , py = zip ( * Points ) plt . сюжет ( px , py , 'или' )plt . показать ()
Пример кода на Unity C #
using UnityEngine ; using System.Collections ; using System.Collections.Generic ;public class Catmul : MonoBehaviour {// Используйте преобразования GameObject в трехмерном пространстве в качестве ваших точек или определите массив с желаемыми точками public Transform [] points ;// Сохраняем точки на кривой Катмулла, чтобы мы могли их визуализировать List < Vector2 > newPoints = new List < Vector2 > ();// Сколько точек вы хотите на кривой uint numberOfPoints = 10 ;// Параметрическая константа: 0,0 для однородного сплайна, 0,5 для центростремительного сплайна, 1,0 для хордового сплайна public float alpha = 0,5f ;///////////////////////////////void Update () { CatmulRom (); }void CatmulRom () { newPoints . Очистить ();Vector2 p0 = points [ 0 ]. положение ; // Vector3 имеет неявное преобразование в Vector2 Vector2 p1 = points [ 1 ]. положение ; Vector2 p2 = points [ 2 ]. положение ; Vector2 p3 = points [ 3 ]. положение ;float t0 = 0,0f ; float t1 = GetT ( t0 , p0 , p1 ); float t2 = GetT ( t1 , p1 , p2 ); float t3 = GetT ( t2 , p2 , p3 );for ( float t = t1 ; t < t2 ; t + = (( t2 - t1 ) / ( float ) numberOfPoints )) { Vector2 A1 = ( t1 - t ) / ( t1 - t0 ) * p0 + ( t - t0 ) / ( t1 - t0 ) * p1 ; Vector2 A2 = ( t2 - t ) / ( t2 - t1 ) * p1 + ( t - t1 ) / ( t2 - t1 ) * p2 ; Vector2 A3 = ( t3 - t ) / ( t3 - t2 ) * p2 + ( t - t2 ) / ( t3 - t2 ) * p3 ; Vector2 B1 = ( t2 - t ) / ( t2 - t0 ) * A1 + ( t - t0 ) / ( t2 - t0 ) * A2 ; Вектор2 B2 = ( t3 - t ) / ( t3 - t1 ) * A2 + ( t - t1 ) / ( t3 - t1 ) * A3 ; Вектор2 C = ( t2 - t ) / ( t2 - t1 ) * B1 + ( t - t1 ) / ( t2 - t1 ) * B2 ; newPoints . Добавить ( C ); } }float GetT ( float t , Vector2 p0 , Vector2 p1 ) { float a = Mathf . Pow (( p1 . X - p0 . X ), 2.0f ) + Mathf . Pow (( p1 . Y - p0 . Y ), 2.0f ); float b = Mathf . Pow ( a , альфа * 0,5f ); возврат ( b + t ); }// Визуализируем точки void OnDrawGizmos () { Gizmos . color = Цвет . красный ; foreach ( Vector2 temp в newPoints ) { Vector3 pos = new Vector3 ( temp . x , temp . y , 0 ); Вещи . DrawSphere ( pos , 0.3f ); } } }
Для реализации в трехмерном пространстве после преобразования точек Vector2 в Vector3 первая строка функции GetT должна быть изменена на это: Mathf.Pow((p1.x-p0.x), 2.0f) + Mathf.Pow((p1.y-p0.y), 2.0f) + Mathf.Pow((p1.z-p0.z), 2.0f);
Пример кода в Unreal C ++
float GetT ( float t , float alpha , const FVector & p0 , const FVector & p1 ) { auto d = p1 - p0 ; float a = d | d ; // Точечное произведение float b = FMath :: Pow ( a , alpha * .5f ); возврат ( b + t ); }FVector CatMullRom ( const FVector & p0 , const FVector & p1 , const FVector & p2 , const FVector & p3 , float t / * между 0 и 1 * / , float alpha = .5f / * между 0 и 1 * / ) { float t0 = 0,0f ; float t1 = GetT ( t0 , alpha , p0 , p1 ); float t2 = GetT ( t1 , alpha , p1 , p2 ); float t3 = GetT ( t2 , alpha , p2 , p3 ); t = FMath :: Lerp ( t1 , t2 , t ); FVector A1 = ( t1 - t ) / ( t1 - t0 ) * p0 + ( t - t0 ) / ( t1 - t0 ) * p1 ; FVector A2 = ( t2 - t ) / ( t2 - t1 ) * p1 + ( t - t1 ) / ( t2 - t1 ) * p2 ; FVector A3 = ( t3 - t ) / ( t3 - t2 ) * p2 + ( t - t2 ) / ( t3 - t2 ) * p3 ; FVector B1 = ( t2 - t ) / ( t2 - t0 ) * A1 + ( t - t0 ) / ( t2 - t0 ) * A2 ; FVector B2 = ( t3 - t ) / ( t3 - t1 ) * A2 + ( t - t1 ) / ( t3 - t1 ) * A3 ; FVector C = ( t2 - t ) / ( t2 - t1 ) * B1 + ( t - t1 ) / ( t2 - t1 ) * B2 ; return C ; }
Смотрите также
Рекомендации
- ^ Catmull, Эдвин ; Ром, Рафаэль (1974). «Класс локальных интерполирующих сплайнов». В Барнхилле, Роберт Э .; Ризенфельд, Ричард Ф. (ред.). Компьютерный геометрический дизайн . С. 317–326. DOI : 10.1016 / B978-0-12-079050-0.50020-5 . ISBN 978-0-12-079050-0.
- ^ Барри, Филип Дж .; Гольдман, Рональд Н. (август 1988 г.). Рекурсивный алгоритм вычисления для класса сплайнов Катмалла – Рома . Труды 15-й ежегодной конференции по компьютерной графике и интерактивным методам, SIGGRAPH 1988. 22 . Ассоциация вычислительной техники . С. 199–204. DOI : 10.1145 / 378456.378511 .
- ^ Юксель, Джем; Шефер, Скотт; Кейзер, Джон (июль 2011 г.). «Параметризация и приложения кривых Катмалла-Рома» . Компьютерный дизайн . 43 (7): 747–755. CiteSeerX 10.1.1.359.9148 . DOI : 10.1016 / j.cad.2010.08.008 .
- ^ Джен Хонг, Тан; Ачарья, У. Раджендра (2014). «Активная сплайн-модель: интерактивная сегментация на основе модели» (PDF) . Цифровая обработка сигналов . 35 : 64–74. arXiv : 1402,6387 . DOI : 10.1016 / j.dsp.2014.09.002 . S2CID 6953844 .
Внешние ссылки
- Кривая Катмулла-Рома без куспидов и самопересечений - реализация на Java
- Кривая Катмулла-Рома без выступов и самопересечений - упрощенная реализация на C ++
- Сплайны Catmull-Rom - интерактивная генерация через Python в записной книжке Jupyter