Это про построение сплайнов с помощью окружностей. Не уверен, что я объясню лучше чем там написано, но вот кратко:
1. Заданы контрольные точки P[0..N]
2. Для отрезка между точками P[i] и P[i+1] строятся две дуги окружности. Первая окружность строится по точкам P[i-1],P[i],P[i+1], а вторая P[i],P[i+1],P[i+2]. Дуга везде берется от P[i] до P[i+1].
3. Для каждой дуги нужно получить параметрическое представление Arc(t=0..1) такое что Arc(0) = P[i], а Arc(1)=P[i+1]
4. Для каждого t значения Arc для каждой из дуг неким образом смешиваются, чтобы получилось плавно.
Проблема у меня в пункте 3. А именно: имея три точки A, B, C, получить параметрическое дуги от B до C.
Вроде бы все вполне понятно: находим центр окружности (просто пересечение срединных перпендикуляров AB и BC), находим радиус, углы начальный и конечный. Вопросы возникают в вырожденных случаях: если ABC лежат на одной прямой, то уже радиус бесконечный.
Есть ли какой-то способ получить такое, без условных операторов.
Здравствуйте, Рома Мик, Вы писали:
РМ>Проблема у меня в пункте 3. А именно: имея три точки A, B, C, получить параметрическое дуги от B до C. РМ>Вроде бы все вполне понятно: находим центр окружности (просто пересечение срединных перпендикуляров AB и BC), находим радиус, углы начальный и конечный. Вопросы возникают в вырожденных случаях: если ABC лежат на одной прямой, то уже радиус бесконечный. РМ>Есть ли какой-то способ получить такое, без условных операторов.
Нужно вместо радиуса использовать кривизну — величину, обратную радиусу. Тогда для прямой значение кривизны будет равно нулю.
Поскольку для angle-based blending нужна даже не кривизна, а угол, то есть смысл оперировать углом касательной дуги к её хорде.
Для дуги, вырожденной в хорду, ясное дело, угол равен 0.
Как находить точки дуги по хорде и углу касательной — тут надо подумать.
Здравствуйте, Кодт, Вы писали:
К>Как находить точки дуги по хорде и углу касательной — тут надо подумать.
Если параметрически (то есть точку от числа t), то будет формула с выражением типа sin(angle*t)/angle. Как его без ифа вычислить — не знаю даже. Самому тейлора забабахать разве что.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Рома Мик, Вы писали:
РМ>Читал вот это: http://www.eecs.berkeley.edu/~sequin/TALKS/SIGG03_Csplines.ppt
РМ>Проблема у меня в пункте 3. А именно: имея три точки A, B, C, получить параметрическое дуги от B до C. РМ>Вроде бы все вполне понятно: находим центр окружности (просто пересечение срединных перпендикуляров AB и BC), находим радиус, углы начальный и конечный. Вопросы возникают в вырожденных случаях: если ABC лежат на одной прямой, то уже радиус бесконечный. РМ>Есть ли какой-то способ получить такое, без условных операторов.
Вот же цитата из этой статьи:
To handle robustly the case of arcs of arbitrary large radii, including straight-line connections between Pi and Pi+1, the point P(u) traveling on Arc(u) is parametrically described as a distance f(u) = |Pi,Pi+1| sin(u τ(u)) / sin(τ(u)) from endpoint Pi and a deviation angle φ(u) = (1-u) τ(u) from line segment (Pi,Pi+1).
Здравствуйте, watchmaker, Вы писали:
W>Вот же цитата из этой статьи:
Слона-то я и не приметил. Статью вообще не читал, как-то не подумал, что она есть и ее можно найти, только презентацию. А в презентации последние слайды промотал, т.к. всякие штуки в трехмерном пространстве меня не интересовали. Буду читать статью...
Здравствуйте, Кодт, Вы писали:
К>Поскольку для angle-based blending нужна даже не кривизна, а угол, то есть смысл оперировать углом касательной дуги к её хорде.
Взял и все сразу правильно придумал!
К>Как находить точки дуги по хорде и углу касательной — тут надо подумать.
Как подсказали, есть статья и в ней подробно описано. Я даже понял.
Есть три точки A, B, C. Угол ABC (на картинке — a) равен половине дуги (AC.
Углы между касательными в точках A и C и прямой AC равны половине дуги (AC, то есть равны углу ABC.
Теперь отдельно рассмотрим AC и угол b, под которым проходят через точки A и C касательные к новой окружности, хордой которой является AC.
Дуга (AC в этой новой окружности равна 2 * b
Пусть точка P(t=0..1) плавно едет от A к C по дуге (AC.
Дуга (AP = (AC * t = 2 * b * t
Дуга (PC = (AC * (1 — t) = 2 * b * (1 — t)
Угол PAC = (PC / 2 = b * (1 — t)
Длина хорды, как пишут в интернете, равна 2R*sin(alpha)2R*sin(alpha/2)
Т.е. AC = 2R * sin( (AC ) Тогда AP = 2R * sin( (AP ) = 2R * sin( (AC*t ) = AC * sin( (AC * t) = AC * sin( 2 * b * t)
Тогда AP = 2R * sin( (AP ) = 2R * sin( (AC / 2 *t ) = AC * sin( (AC / 2 * t) / sin( (AC / 2 ) = AC * sin( 2 * b * t) / sin( b )
Осталось отметить, что как уже говорили (AC равно углу касательной к окружности в точке A и AC.
Угол PAC и длина AP однозначно задают положение точки P.
PS Еще стоит отметить, что изначальному условию это решение не удовлетворяет, т.к. для варианта b == 0 + PI*N остается деление на ноль. На практике я просто при значениях угла близких к 0 или PI немного меняю угол: расчеты остаются стабильными и при углах около 1e-200 радиан, а на глаз ничего не заметно даже при 1e-2.
PPS по углу касательной и хорды b и длине хорды L можно получить кривизну: L = 2R*sin(b) => 1/R = 2*sin(b)/L