На следующем рисунке показано, чего я пытаюсь достичь:
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
Параллельные линии и кривые by Charles Petzold может быть одним из способов решения этой проблемы. На самом деле он работает довольно хорошо, но он сглаживает кривых, что создает визуальные артефакты при глубоком увеличении, и, конечно, есть недостаток производительности.
Однако алгоритм не пытается найти кривую Безье, параллельную другой кривой Безье. Вместо этого алгоритм полностью основан на полилиниях: входные данные представляют собой одну или несколько полилиний, а выходные данные состоят из нескольких полилиний для каждой входной полилинии. По этой причине ParallelPath необходимо «сгладить» входную геометрию, что означает преобразование всей геометрии (включая дуги и кривые Безье) в аппроксимацию полилинии.
Обновление № 2
Таким образом, мой друг (математик, доктор философских наук) проанализировал эту проблему, и создание параллельной кривой для (третьего порядка) Кривая Безье очень сложно и вычислительно дорого. Для каждой точки параллельной кривой компьютер должен будет вычислить что-то вроде этого:
(degree 3 polynomial) + (degree 2 polynomial) / sqrt(degree 4 polynomial)
Возможно, есть способ оптимизировать это выражение, но оно все равно будет НАМНОГО БОЛЬШЕ вычислительно дороже, чем стандартная кривая Безье (поскольку параллельная кривая - это совершенно другая кривая, чем исходная кривая Безье). Я хочу иметь возможность анимировать кривую, поэтому это решение, вероятно, будет слишком дорогим для процессора. Это оставляет нам пару вариантов:
Используйте Чарльз Петцольд аппроксимация ломаной линии, которая творит чудеса, но при глубоком увеличении есть визуальные сбои.
Получите наше собственное приближение, основанное на приближении Чарльза Петзонда. Используйте кривые Безье вместо линий (возможно, будет достаточно дуг). Это решило бы проблему глубокого масштабирования, но, вероятно, это довольно сложно для кодирования (я понятия не имею, как это сделать).
Может быть, возможно создать что-то вроде двухцветной кисти. Таким образом, мы могли бы использовать только один Path
для достижения желаемого результата (как показано на первом изображении). Хотя я нигде не видел, так что это, вероятно, не вариант.
Обновление № 3
Я нашел несколько довольно интересных ссылок:
Подробнее:
- QPainterПредполагается, что PathStroker из среды Qt использует алгоритм Томаса Ф. Хейна для параллельных кривых
- Этот Java Stroker также должен быть способен рисовать параллельные кривые
Может быть, окончательное решение? (источник здесь )
... Я разработал все, что я знал о теории кривых Безье, и разработал несмещенное смещение к чему-то правильному, и (монстр) задокументировал это на Учебник для начинающих на кривых Безье
Попытка # 1
Сделайте второй путь немного шире и сдвиньте его под первым путем, используя Z-Index.
http://i51.tinypic.com/2r5vwjk.png
Это не сработает, Geometry
необходимо соответствующим образом преобразовать.