Russian Qt Forum

Программирование => Общий => Тема начата: Igors от Декабрь 21, 2017, 16:37



Название: Редактирование кривых
Отправлено: Igors от Декабрь 21, 2017, 16:37
Добрый день

Давно заметил что любые манипуляции со временем воспринимаются очень трудно. Во всяком случае, меня капитально клинит - возможно это тот самый случай.

На первом скриншоте 2 графика X и Y от времени. Кривые имеют по 3 контрольных точки (рисуются если кривая выбрана). Каждая точка имеет синие ручки которые юзер может драгать (часто называют knot(s)) и таким образом управлять кривизной. У каждой контрольной точки 2 параметра

angle - угол наклона синего отрезка относительно горизонтали (времени)
weight - длина синего отрезка (чем больше тем мощнее кривизна)

Как пересчитать angle и weight  если юзер двигает синие точки на концах отрезка? Ну ясно, отняли от синей точки саму контрольную, получили вектор (половинка синего отрезка). И просто atan2 - получили angle, а weight = длине отрезка. Элементарщина.

А теперь мы рисуем путь (второй скриншот). Ну или "траекторию". И тут у нас есть кноты, мы их рисуем просто взяв высоты синих отрезков из первого скриншота, т.е.
Код:
x = sin(curve_x.point[1].angle) * curve_x.point[1].weight; 
y = sin(curve_y.point[1].angle) * curve_y.point[1].weight;
Да, но как же теперь пересчитать angle и weight если юзер двигает кноты ??? Ведь времени по второй оси уже нет. Правду сказать, совсем растерялся солдат  :)

Спасибо




Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 22, 2017, 07:53
Зря вы связались с отдельными компонентами x и y, лучше выписывать зависимости в общем параметрическом виде прямо в точках пространства P = {x, y, ...} в виде зависимости P = P(t).
Тогда все будет выражаться не в углах и весах, а в полиномах, их производных и координатах узловых точек.
Полином для производной по t даст направление касательной в каждой точке кривой.

Как только будет понятно какой вид кривых Вы рисуете (Безье, NURBS, В-сплайны или др.), можно будет помочь с вычислением интересующих параметров.



Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 22, 2017, 09:14
Тогда все будет выражаться не в углах и весах, а в полиномах, их производных и координатах узловых точек.
Полином для производной по t даст направление касательной в каждой точке кривой.
А здесь обратная задача - юзер "задает производную" (ну управляет углом наклона касательной). Задание углов и весов - изменить не могу, тем более это стандартная практика.

Как только будет понятно какой вид кривых Вы рисуете (Безье, NURBS, В-сплайны или др.), можно будет помочь с вычислением интересующих параметров.
Ладно, я тоже блесну эрудицией :) Это F-Curve. Синие вектора вычисляются без затей (на основании угла и веса). Но интерполяция почему-то не обычной эрмитной матрицей, а полиномом Бернштейна (не знаю почему). Но никакого отношения к теме это не имеет  :)

Может вообще решения нет, ну т.е. получить вектор из угла и веса - пожалуйста, но не наоборот. Уже засомневался.

Да, а где же научные работники, аспиранты и др? Ну как всегда.... заняты "сессией", гульками с собачкой и рисованием темплейтов - не дождесся  :'(


Название: Re: Редактирование кривых
Отправлено: ViTech от Декабрь 22, 2017, 14:37
На самом деле концепция времени достаточно проста:

(http://a.radikal.ru/a28/1712/f0/919807a0c9ac.png)

Путём нехитрых манипуляций по удалению лишних временных размерностей получаем следующую модель:

(http://c.radikal.ru/c31/1712/53/1a0c2296875d.jpg)

Далее избавляемся от времени вовсе:

(http://d.radikal.ru/d21/1712/54/9a9b6f78a97e.png)

На данном этапе имеем двумерное пространство, где нам досаждают углы и длины векторов. У нас уже есть опыт избавления от ненужных осей пространства, поэтому с лёгкой душой отсекаем всё лишнее (да, мы не только хорошие программисты, но и скульпторы тоже).  Всё сворачивается в нулевое пространство:

(http://c.radikal.ru/c24/1712/2c/ad6dbb0cfadb.jpg)

Нет пространства - нет проблем. Задача решена, можем расходиться на выходные.

...

Или нет?

Сингулярность может породить альтернативную вселенную. Она даже может переплетается с нашей вселенной:

(http://c.radikal.ru/c37/1712/86/139ed77b2f32.jpg)

В этой вселенной человечество уже  сталкивалось с подобными задачами и успешно их решало. Доказательством этого могут послужить различные графические редакторы, которые работают с такими кривыми (за альтернативную вселенную мы точно про существование таких редакторов не знаем, но можем предполагать, что они таки там есть). Возможно то человечество умеет работать с проекциями. Одно можно утверждать совершенно точно: человечество в альтернативной вселенной намного ответственней, чем в нашей. Научные работники (как старшие, так и младшие) сидят на своих рабочих местах и корпят над решением глобальных проблем вселенной (как своей, так и других). Аспиранты им в этом усердно помогают: строят сечения и проекции многомерных пространств, и ломают голову, как из нулевого пространства развернуть хотя бы трёхмерное. Собачки понимают ответственность своей вселенной перед другими и сами себя выгуливают. Заодно приносят горячие обеды и бутерброды для перекуса своим хозяевам.

Есть ли в этой альтернативной вселенной Igors? Наверняка есть, эту задачу уже решил и теперь спешит к своему побратиму на помощь:

(http://a.radikal.ru/a08/1712/87/85760368a4f4.jpg)

Igors в нашей вселенной остаётся только написать правила преобразования координат между пространствами различной размерности. Чтобы из нулевого пространства, порождённого сингулярностью чёрной дыры из альтернативной вселенной, "распаковать"  пространство достаточной размерности, в котором альтер Igors сможет показать решение поставленной задачи настоящему Igors.

Кстати. Если есть комната-библиотека, самое время туда заглянуть, может решение там уже есть:

(http://c.radikal.ru/c26/1712/df/17c04d17683f.jpg)

Решение может быть в бинарном виде, но мыжпрограммисты!


Название: Re: Редактирование кривых
Отправлено: kambala от Декабрь 22, 2017, 16:09
лучший пост года (а то и всего форума)


Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 23, 2017, 06:59
ViTech, спасибо за красочный пост, мне тоже понравилось. Общение с научными работниками вообще интересно, иногда узнаю много нового, часто ловлю себя на мысли "да я же это знал" (но не понимал). Но увы, к решению практической задачи это никак не приближает. Не, я вовсе не хочу сказать что они - бездельники, проедающие гранты (популярное мнение) - но толку никогда не было, и, видимо, не будет.  

Воспользоваться "готовыми проверенными решениями" - а он, ленивец, не хочет гуглу открыть! Это всего лишь "удобное объяснение", в таких ситуациях шансов найти что-то стоящее немного - задачка "не так популярна".

И вообще, верна ли постановка? Ведь если нет - то любые поиски ничего не дадут. И еще вполне возможный вариант - решается простейшими школьными знаниями. Хорошо, зафиксируем weight и пусть он одинаков для X и Y, т.е. драг юзера меняет только angle(s). Опять все элементарно, углы вычисляются через asin или atan(2). Значит как минимум одно решение уже есть - сделать один драг для углов, другой (с зажатой клавишей - а шо делать) для весов. Это конечно не очень удобно, хотелось бы обойтись одним. Но возможно ли?

Все-таки странно что такие простейшие соображения не приходят в голову(?) людям занятыми глобальными проблемами и чьи знания в 100 раз больше. Ладно, (тактично) предположим они слишком увлечены своими делами  :)


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 25, 2017, 08:49
А здесь обратная задача - юзер "задает производную" (ну управляет углом наклона касательной). Задание углов и весов - изменить не могу, тем более это стандартная практика.

Юзер "задает" положение точек относительно друг друга. Параметрический вид кривой может быть выражен через их координаты.
А всякие углы и веса - это уже следствие взаимного расположения положения этих точек.

В случае, если пользователь не передвигает узловые точки, а явно задает веса и углы в GUI, то нужно в аналитическом виде, исходя из параметрического вида кривой, выразить зависимость координат узловых через веса и углы.
Такой подход не очень то гибкий, особенно, если рассматривать больше 2-х измерений. Если с зависимостями между углами и координатами крайних узловых точек все достаточно ясно (тангенс угла - отношение разниц координат по X и Y), то с другими параметрами формулы могут оказаться намного сложнее.

И все-таки хотелось бы увидеть аналитическую форму кривой, чтобы хоть что-то помочь сделать). Без нее любые советы будут только общими словами.


Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 25, 2017, 10:40
Юзер "задает" положение точек относительно друг друга. Параметрический вид кривой может быть выражен через их координаты.
А всякие углы и веса - это уже следствие взаимного расположения положения этих точек.
Есть и такое, это кривая "по умолчанию" которая автоматом подстраивается когда юзер двигает сами контрольные точки. Конечно "usable", но, ясно, не всегда устраиваетю

В случае, если пользователь не передвигает узловые точки, а явно задает веса и углы в GUI,
Да, здесь задача стоит именно так.

то нужно в аналитическом виде, исходя из параметрического вида кривой, выразить зависимость координат узловых через веса и углы.
Такой подход не очень то гибкий, особенно, если рассматривать больше 2-х измерений. Если с зависимостями между углами и координатами крайних узловых точек все достаточно ясно (тангенс угла - отношение разниц координат по X и Y), то с другими параметрами формулы могут оказаться намного сложнее.
Тут я Вас не понял. См аттач, обычный кубический Безье. Всего 4 точки, 2 из них лежат на самой кривой (контрольные/узловые), 2 других "управляющие"(точки на концах синего вектора). Юзер может двигать любую из них НО это вовсе не меняет другие автоматом. Напр изменение управляющей точки изменит только ее саму, изменение узловой - не изменит вектор узловая-управляющая (он просто будет сдвинут). Здесь узловые задаются углом + весом, т.е. по сути все то же.

И все-таки хотелось бы увидеть аналитическую форму кривой, чтобы хоть что-то помочь сделать). Без нее любые советы будут только общими словами.
А что здесь "аналитическая форма"? Как вычисляются начальные вектора:
Код:
point[i].angle = atan2(point[i + 1].value - point[i - 1].value, point[i + 1].time - point[i - 1].time);
Ну так это всего лишь default, дальше юзер меняет его как угодно.

Рисование кривой (значение от времени): находится сегмент кривой, для него есть 4 точки, первая и последняя - сами контрольные точки кривой, 2 другие - управляющие (синий вектор). Время приводится к относительному: t = 0 первая точка, t = 1 последняя. Дальше так (псевдокод)
Код
C++ (Qt)
double k[4];
Calculate(t, k);
return p0.value * k[0] + p1.value * k[1] + p2.value * k[2] + p3.value * k[3];
 
Собсно вся "аналитика" в ф-ции Calculate - как считать коэффициенты сплайна, углубляться в нее необязательно. И все хорошо, юзер может менять value для X, Y и Z на отрисованном пути, но каким angle+weight это соответствует для каждой компоненты? Ведь нужно предъявить не только путь, но и график каждой от времени.

Думал взять производную в начальной и конечной точках (это ведь и есть тангенс угла). Но тогда что делать с weight (вес один на всех)?

Та же проблема возникает и при другом раскладе. Для Безье сплайна нет "угол + вес", а есть просто "вектор". И опять хз как рисовать "компоненту от времени".

[off]ssoft, меня порадовал Ваш ответ. Уже думал типа "что толку постить? Ото увидело "atan2" и убежало саттера читать". Ан нет, есть нормальные люди![/off]


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 25, 2017, 15:16
Судя по описанию, в задаче используется кривая в виде NURBS https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline, а никакой не Безье).
Сплайн 3-го порядка с весами для каждой из 4-х узловых точек. А угол в каждой точке кривой определяется годографом - производной, которая является сплайном 2-го порядка (навряд ли нужен в Вашей задаче).

Для этого представления веса для точек задаются только явно. Никакое перемещение точек на веса не влияет.
Для изменения углов не понятен способ использования - пользователь вводит значение угла для конечных точек? для всех точек? ожидается влияние на саму точку? на следующую? на предыдущую?
Можете, например, изменять наклон отрезков между точками (угол без модуля вектора влияет только на наклон). Дальше тоже вариации, одна из точек неподвижна и расстояние до искомой фиксировано? Или наклон относительно следующей должен остаться неизменным? Эти вопросы появляются так как неизвестна величина производной, а есть только отношение.

Может следует ограничиться только интерактивным перемещением точек и явным заданием весов? Все сразу намного проще становится).

Цитировать
И опять хз как рисовать "компоненту от времени".

Здесь то все предельно просто. Параметрический вид - это и есть зависимость от "времени" t. Вместо точки нужно брать значение соответствующей компоненты.
К сожалению не могу много времени уделить Вашему вопросу, конец года)). Попробуйте разобраться пока сами. Я буду подключаться по мере возможности.


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 25, 2017, 15:33
Вот еще).
Параметрический вид Вашей кривой наверное такой.

(http://nurbs.png)


Название: Re: Редактирование кривых
Отправлено: ViTech от Декабрь 25, 2017, 15:49
Параметрический вид Вашей кривой наверное такой.

Это вряд ли. В формуле atan2 должон быть, иначе не страшно.


Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 26, 2017, 10:52
Для этого представления веса для точек задаются только явно. Никакое перемещение точек на веса не влияет.
Для изменения углов не понятен способ использования - пользователь вводит значение угла для конечных точек? для всех точек? ожидается влияние на саму точку? на следующую? на предыдущую?
Для каждого сегмента кривой есть 4 точки. При изменении юзером любой из них все остальные остаются неизменны, меняется лишь кривизна сегмента (см примеры в аттаче). Я могу рисовать синие вектора как на параметрических графиках x(t), y(t), z(t), так и на пути в 3D окне (для простоты на плоскости XOZ, здесь принципиальной разницы 2D и 3D нет). Все рисуется корректно НО мне надо интерактивно редактировать и там и сям - а я не сообразю как это делать

Здесь то все предельно просто. Параметрический вид - это и есть зависимость от "времени" t. Вместо точки нужно брать значение соответствующей компоненты.
Для пути используется только значение компонент(ы). Для параметрического графика - значение и время t (то же самое выражается углом + длиной). Имея "только значение" (для Безье) я могу спокойно редактировать кривизну пути, но как отразить эти изменения в параметрическом графике? А имея угол+вес (для F-Curve) - как я должен их менять при редактировании пути?

Параметрический вид Вашей кривой наверное такой.
Да наверняка есть и такой, там сплайнов целая свора, и, конечно, не я их писал. Все эти длинные сопли формул я имею - ну и что с ними делать?


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 26, 2017, 16:13
Я так понял, что хотелось бы реализовать что-то подобное https://www.lynda.com/CINEMA-4D-tutorials/F-curve-manipulation/508543/550216-4.html

Судя по видео реализовано что-то типа:

* Произведена разбивка на интервалы времени интерполяции путем установки ключевых кадров. Причем разбивка по компонентам может быть различная.
* На каждом отрезке интервал времени нормируется в диапазон [0,1] (линейный закон, чтобы значение времени перевести в параметр сплайна).
* Для нормированного диапазона задается аналитический вид (формула с весами). По-умолчанию все веса равны 1.
* Движение точки ключевого кадра вверх/вниз влияет только на компоненту крайней ключевой точки. Движение вправо/влево - на время ключевого кадра.
* Движение точки вектора вверх/вниз влияет на компоненту внутренней ключевой точки. Движение вправо/влево - на вес внутренней ключевой точки (веса крайних точек не изменяются).

Если разбивка по компонентам независимая, то изменение одного графика никак не влияет на другой (я бы реализовал так).
Если компоненты образуют единый сплайн, то на графиках все точки имеют одинаковую координату по времени, а значения не редактируемых компонент корректируются, чтобы сохранялось w*X = const  (X - корректируемая компонента).

И вопрос - Вам нужно точно математически повторить функциональность или достаточно сделать похоже?
Можно открыть исходники blander какого-нибудь.


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 26, 2017, 17:11
Еще вариант, если компоненту "время" ввести в точку к пространственным координатам.
Тогда любой график - это двумерная проекция (или отдельный сплайн) одной пространственной координаты и времени.
И не нужно никаких весовых коэффициентов, можно обойтись чистым Безье.

Остается только для нужного времени вычислить значение параметра, с помощью аналитического решения кубического уравнения.


Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 27, 2017, 13:19
Я так понял, что хотелось бы реализовать что-то подобное
Берем выше - уже реализовано, шлифуем детали  :)

* Произведена разбивка на интервалы времени интерполяции путем установки ключевых кадров. Причем разбивка по компонентам может быть различная.
* На каждом отрезке интервал времени нормируется в диапазон [0,1] (линейный закон, чтобы значение времени перевести в параметр сплайна).
* Для нормированного диапазона задается аналитический вид (формула с весами). По-умолчанию все веса равны 1.
* Движение точки ключевого кадра вверх/вниз влияет только на компоненту крайней ключевой точки. Движение вправо/влево - на время ключевого кадра.
* Движение точки вектора вверх/вниз влияет на компоненту внутренней ключевой точки. Движение вправо/влево - на вес внутренней ключевой точки (веса крайних точек не изменяются).
Да, все так, это делают все, изобрести что-то другое трудно, да и не нужно

Если разбивка по компонентам независимая, то изменение одного графика никак не влияет на другой (я бы реализовал так).
Трудно представить "зависимую", это как? Редактирование X(t) каким-то образом влияет на Y(t)? Таких задач у меня нет.

И вопрос - Вам нужно точно математически повторить функциональность или достаточно сделать похоже?
Не знаю что повторять. Если компонент 2 или 3, то мне нужно редактировать как кривизну пути, так и кривизну каждой компоненты от времени. Вот собсно и вся задача/проблема

Можно открыть исходники blander какого-нибудь.
Наверное "Blender'a". А Вы сами пробовали их открывать?  :) Я да, раз 5 (не по этой теме конкретно). И всякий раз, после пары дней разборок - ну да, что-то новое узнал, но чего-то конкретного не получил ни разу.  Код задроченый капитально (даже для моих либеральных мерок). Дело не в том что я (якобы) "не хочу искать", а в том что неясно "что искать", и есть ли оно вообще.

Еще вариант, если компоненту "время" ввести в точку к пространственным координатам.
Тогда любой график - это двумерная проекция (или отдельный сплайн) одной пространственной координаты и времени.
Не понял. Юзер выбрал любую контрольную точку на пути. Разумеется известно какому времени она соответствует. И... что с того?

И не нужно никаких весовых коэффициентов, можно обойтись чистым Безье.
У меня нет свободы выбора "чем обойтись", есть 2 сплайна позволяющие редактировать путь (F-Curve и Безье), ф-ционал должен быть реализован для обоих


Название: Re: Редактирование кривых
Отправлено: ssoft от Декабрь 28, 2017, 09:44
Зависимая разбивка на компоненты - это когда рассматриваются один сплайн вида P{X,Y,Z}(t) или P{X,Y,Z,t}(u).
Независимая - когда для каждой пространственной компоненты отдельный сплайн P{X}(t) или P{X,t}(u), P{Y}(t) или P{Y,t}(v), P{Z}(t) или P{Z,t}(w).

Если хочется иметь в пространстве {X,Y,Z} "управляющие" точки одного и того же сплайна, то компоненты "связаны" друг с другом единым параметрическим описанием кривой.
Если же для P{X}(t), P{Y}(t), P{Z}(t) зависимости отдельные, то не о каких "управляющих" точках в пространстве речи быть не может. Здесь могут быть только точки ключевых кадров и расстановка меток времени вдоль траектории.

Вернемся к первому случаю, когда для всех пространственных компонент имеется единый сплайн P{X,Y,Z}(t).

Рассмотрим графики в пространстве {X, t}, {Y, t}, {Z, t} и управляющие векторы. Тангенс угла наклона вектора дает значение производной пространственной компоненты по времени в точке, собственно скорость движения в вдоль компоненты.
Что определяет длина вектора? Пусть она как то влияет на вторую производную (ускорение), например, будет пропорциональна ее величине.

Для простоты рассмотрим сплайн Безье третьего порядка.
И первую и вторую производную для сплайна Безье можно вычислить аналитически. Значение производной нам даст положение первой точки относительно нулевой. А значение второй производной - сместит вторую точку.
Но вот незадача, в этом случае меняются скорость и ускорение относительно конечной точки, т.е. смещается второй управляющий вектор, а этого нам никак не нужно. Значит наше предположение, что в пространстве кривая представляет собой сплайн Безье, не является верным.

Рассмотрение других форм полиномиальных сплайнов 3-го порядка приведут к такому же результату. Возможно, корректный результат дадут сплайны 5-го порядка с 6-ю управляющими точками вместо 4-x. Это можно проверить аналитически)).
То есть для двух точек и управляющих векторов в пространствах {X, t}, {Y, t}, {Z, t} в пространстве {X,Y,Z} должно быть шесть управляющих точек сплайна.

Другой вариант, когда  зависимости {X, t}, {Y, t}, {Z, t} сами представляют собой сплайны Безье P{X,t}(u), P{Y,t}(v), P{Z,t}(w). Если судить по видео из моего предыдущего сообщения, то там представлен именно этот вариант.
Кстати, в том же видео никаких управляющих точек в пространстве {X,Y,Z} не представлено. Ограничение перемещения управляющих точек сплайна Безье вдоль оси t, гарантирует монотонное возрастание t относительно параметра. Таким образом для каждого значения t имеется единственное вещественное значение параметра (u,v или w), которое может быть вычислено аналитически (корень решения кубического уравнения).

Таким образом, схема построения пространственной траектории такая - в пространствах {X,t}, {Y,t}, {Z,t} в виде F-curves задаются параметрические зависимости. Эти зависимости могут представлять собой функции вида X(t) (например, Easing curve) или сплайны P{X,t}(u) (например, Безье). Для определения пространственных координат для заданного значения t необходимо по этим зависимостям определить значения X,Y,Z. В случае X(t) - тривиально подставляем t, получаем результат. В случае сплайнов, решаем уравнение t(u)=t0 (t0 - текущий момент времени), получаем значение параметров (u,v,w), для которых получаем соответствующие значения X,Y и Z.



Название: Re: Редактирование кривых
Отправлено: Igors от Декабрь 28, 2017, 10:58
Зависимая разбивка на компоненты - это когда рассматриваются один сплайн вида P{X,Y,Z}(t) или P{X,Y,Z,t}(u).
Независимая - когда для каждой пространственной компоненты отдельный сплайн P{X}(t) или P{X,t}(u), P{Y}(t) или P{Y,t}(v), P{Z}(t) или P{Z,t}(w).
Ага, вот так - ну тогда у меня есть и те и другие. Т.е. в первом случае компоненты X, Y. Z - один "вектор" и любая контрольная точка существует для всех компонент. Во втором случае у каждой компоненты свои контрольные точки, их число может быть разным. НО путь может интерактивно редактироваться только для первого случая (вектор), и это правильно, если поразмыслить во втором случае ничего разумного не получить. Собсно какой-то роли это не играет, в любом случае значения независимы

Ну ладно, значит что - надо попробовать взять производную, ничего другого не видно. Сегодня-завтра спробую, отпишусь