Как сделать гладкий путь с учетом набора точек данных? - PullRequest
5 голосов
/ 03 августа 2009

Последние пару дней я ломал голову над рендерингом пути без какого-либо реального решения.

Под рендерингом пути я подразумеваю заданный набор точек данных x, y (на разном расстоянии), чтобы нарисовать пунктирную линию (или в моем случае повернутый квадрат) фиксированной длины через регулярные интервалы между заданными точками набора данных для создания гладкий путь.

Если у вас есть управление полетом для iPhone, я пытаюсь создать эффект, похожий на рендеринг пути в этой игре.

Вот моя проблема. Если ширина графика + зазор не является точной в отношении расстояния между двумя точками набора данных, то мне остается перекрытие или перекрытие. Мое единственное решение это либо

1) Возьмите точку перекрытия / перекрытия за конечную точку следующей заданной точки данных, а затем проведите оттуда к следующей точке.

2) Всегда рисуйте под конечной конечной точкой и начинайте заново со следующей точки данных.

Ни одно из этих решений не является идеальным, и оба имеют проблемы.

У кого-нибудь есть лучшее решение?

Любая помощь будет высоко ценится.

Следующий экран иллюстрирует то, что я пытаюсь создать: http://www.firemint.com/flightcontrol/screenshots-peaceful.html

Толстая пунктирная линия.

Обновление:

Привет. Я попытался выполнить рендеринг с помощью кривых. Я рассчитал кубическую кривую (с помощью 4 контрольных точек). Однако проблема заключается в интерполяции. Учитывая 0 и 1, я могу пройти любые 2 пункта. Однако я хочу пройти весь путь (несколько контрольных точек). Проблема в том, что некоторые контрольные точки будут находиться на разном расстоянии друг от друга, и, таким образом, шаг с постоянным шагом (скажем, 0,2) будет давать неправильные результаты. Я понимаю, что для правильного прохождения всего пути мне нужно рассчитать длину всей кривой ... вопрос в том, как мне это сделать? ... или есть другой способ?

Приветствие Рич

Ответы [ 4 ]

3 голосов
/ 03 августа 2009

Существует функция CoreGraphics под названием «CGPathAddQuadCurveToPoint», которая используется для рисования гладких контуров. Пример его использования на GitHub .

1 голос
/ 03 августа 2009

Возможно, вы захотите взглянуть на кривые Безье или кривые Эрмита их не так сложно вычислить, и вы получите хорошие мягкие кривые.

1 голос
/ 03 августа 2009

Вы, вероятно, должны проверить кривые Безье и Сплайны алгоритмы.

0 голосов
/ 03 августа 2009

Вы полностью ограничены квадратами фиксированного размера? Идеальное решение - обрезать последний квад до правильного размера.

Если вы ограничены, вы можете сделать пару вещей. Если вы рисуете пунктирные линии, вы можете изменять расстояние между ними, чтобы быть уверенным, что у вас никогда не получится частичное квадрирование на конечных точках. Это может отвлекать визуально, так как расстояние будет регулироваться в зависимости от длины сегмента.

редактирование:

Ах, картинка помогает. Я предполагаю, что поскольку это на iPhone, вы получаете ряд точек, из которых рисование линий между ними создает приемлемую кривую. Если это так, использование сплайнов / кривых примитивов, вероятно, излишне. Я, вероятно, подхожу к рисованию линий, как показано, просто рисуя квадраты в каждой точке данных, которая находится на заданном расстоянии от последней точки данных.

Алгоритм будет выглядеть примерно так:

  1. Нарисуйте четырехугольник на первой точке данных (повернут соответствующим образом)
  2. Обходите список точек, пока вы не окажетесь на расстоянии не менее X от последней точки
  3. Отклонение между текущей точкой и последней посещенной точкой, чтобы найти точный центр для размещения следующего квада.
  4. Нарисуйте четырехугольник (повернут соответствующим образом)
  5. Перейти к шагу 2
  6. Если у вас есть частичная точка для последней четверки, нарисуйте ее как обычно (это даст лучший визуальный эффект, чем усечение).

Ради забавы, чтобы перескочить между двумя точками на некоторое расстояние D, которое меньше расстояния между двумя точками (это, вероятно, проще в 2D-случае, но мне нравится работать в целом):

vector v = point2 - point1;
normalize(v);
v *= D;
finalPoint = point1 + v;
...