Следующее изображение иллюстрирует то, что я пытаюсь достичь:
http://i53.tinypic.com/14ugfpd.png
В основном я хочу создать два Path
объекты, которые "касаются друг друга" (параллельные пути). Это XAML используется для генерации этого изображения:
<StackPanel Orientation="Horizontal">
<StackPanel.LayoutTransform>
<ScaleTransform CenterX="0" CenterY="0" ScaleX="15" ScaleY="15" />
</StackPanel.LayoutTransform>
<Grid Margin="-5,0,0,0">
<Path Stroke="Blue">
<Path.Data>
<PathGeometry>M10,10 C20,10 10,20 20,20</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red">
<Path.Data>
<PathGeometry>M10,11 C19,10.85 9,20.80 20,21</PathGeometry>
</Path.Data>
</Path>
</Grid>
<Grid Margin="-5,0,0,0">
<Path Stroke="Blue">
<Path.Data>
<PathGeometry>M10,10 C20,10 10,20 20,20</PathGeometry>
</Path.Data>
</Path>
<Path Stroke="Red">
<Path.Data>
<PathGeometry>M10,11 C19,11 9,21 20,21</PathGeometry>
</Path.Data>
</Path>
</Grid>
</StackPanel>
Первая кривая имеет оптимизированные по рукам позиционные точки, вторая - точечные позиции, которые легко вычисляются, принимая во внимание толщину штриха. Вы можете видеть, что вторая кривая не идеальна, потому что между ними есть пробел. Как я могу создать две совершенно "трогательные" кривые программно, без ручной оптимизации каждой кривой (что на самом деле невозможно, потому что кривые генерируются в коде)?
Проще говоря, я генерирую одну кривую (соответственно Path
) в коде, и мне нужно, чтобы она имела два цвета. Поэтому я думал, что вторая параллель Path
выполнит трюк, но настройка Geometry
второго Path
(чтобы сделать его параллельным) оказалась проблематичной.
Обновление # 1
Параллельные линии и кривые Чарльз Петцольд может быть одним из способов решения этой проблемы. Он действительно работает очень хорошо, но он выравнивает кривые, что создает визуальные артефакты при глубоком увеличении, и, конечно же, есть недостаток в производительности.
Однако алгоритм не пытается найти кривую Безье, параллельную другой кривой Безье. Вместо этого алгоритм основывается исключительно на полилиниях: входной сигнал является одним или несколькими полилиниями, а выход состоит из нескольких полилиний для каждой входной полилинии. По этой причине ParallelPath должен "сгладить" входную геометрию, что означает преобразование всей геометрии (включая дуги и кривые Безье) в приближение полилинии.
Обновление # 2
Итак, мой друг (math Ph.D. inceptor) проанализировал эту проблему и создал параллельную кривую (третий порядок) кривая Безье является очень сложным и вычислительно дорогостоящим. Для каждой точки параллельной кривой компьютер должен был бы вычислить что-то вроде этого:
(degree 3 polynomial) + (degree 2 polynomial) / sqrt(degree 4 polynomial)
Возможно, есть способ оптимизировать это выражение, но он все равно будет MUCH MORE вычислительно дорогим, чем стандартная кривая Безье (потому что параллельная кривая представляет собой совершенно другую кривую, чем исходная кривая Безье). Я хочу иметь возможность оживить кривую, поэтому это решение, вероятно, будет слишком дорогостоящим CPU. Это оставляет нам несколько вариантов:
-
Используйте приближение полилинии Чарльза Петцольда, которое творит чудеса, но при глубоком увеличении зрительные глюки.
-
Выведите собственное приближение, основанное на Чарльзе Петзонде. Используйте кривые Безье вместо линий (возможно, дуг будет достаточно). Это позволило бы решить проблему с глубоким масштабированием, но, вероятно, довольно сложно кодировать (я не знаю, как это сделать).
-
Возможно, можно создать что-то вроде двухцветной кисти. Таким образом, мы могли бы использовать только один
Path
для достижения желаемого результата (как показано на первом изображении). Я его нигде не видел, так что это, вероятно, не вариант.
Обновление # 3
Я нашел несколько интересных ссылок:
- Как компенсировать кубическую кривую безье? (Эвристический алгоритм)
- Контур кривой кубической кривой безье
- расширение пути безье (алгоритм Python)
- Offset Bézier Curves (Java-реализация выборочной полилинии кривой Безье, реализация отличается от Чарльза Петцольда)
- Parallel Bézier (Почему параллельные кривые Безье не возможны с математической точки зрения)
- Быстрое точное сглаживание кубической бумаги Bézier и коррекционной кривой (Ссылка для скачивания 1, Ссылка для скачивания 2)
Дополнительная информация:
- QPainterPathStroker из структуры Qt предполагается использовать алгоритм Томаса Ф. Хейна для параллельных кривых
- Этот Java Stroker также должен быть способен рисовать параллельные кривые
Может быть, окончательное решение? (источник здесь)
... Я разработал все, что знал о теории кривой Безье, и разработал несвязанное смещение к чему-то правильному, и (монстр) документировал, что на Праймер на кривых Безье
Попытка # 1
Сделайте второй путь немного шире и сдвиньте его под первым путем при использовании Z-Index. http://i51.tinypic.com/2r5vwjk.png
Это не сработает, Geometry
должно быть соответствующим образом преобразовано.