SVG path часть 5

Примеры и код команд:

  1. Начальная точка (M,m) и отрезок прямой (L,l)
  2. Горизонтальная линия (H,h) и вертикальная (V,v)
  3. Дуга элипса – Elliptical Arc (A,a)
  4. Кубическая кривая Безье – The cubic Bézier curve
  5. Гладкая поликривая Безье – Smooth cubic poly Bezier curve
  6. Кривые Безье второго порядка – Quadratic Bezier Curves
  7. Гладкая поликривая Безье второго порядка – Smooth Quadratic poly Bezier
  8. Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”

8. Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”

Я думаю, что все, кто рисовал в любом векторном редакторе, встречались с эффектом белых, непрокрашенных пятен при заполнении фигур цветом. Это не вызывало больших проблем и легко устранялось дополнительными щелчками мышки по незакрашенным областям рисунка. Но как быть, если нужно написать скрипт, реализующий анимацию с закрашиванием всей фигуры или её отдельных сегментов?
Для этого нужно чётко разобраться в алгоритме заполнения цветом сегментов фигур. Логично предположить, что должны заполняться внутренние области фигуры, а наружные оставаться незакрашенными.
Но как понять, где внутренняя, а где наружная область фигуры, если она имеет сложные контуры с многократными пересечениями линий. Что брать за точку отсчета, относительно чего смотреть?
Ответы на эти вопросы дает спецификация команды fill-rule, которая имеет два значения:nonzero | evenodd

fill-rule=”nonzero”
Это правило определяет внутреннию точку на холсте, путем рисования луча от этой точки до бесконечности в любом направлении и затем проверяются места, где сегмент фигуры пересекает луч . Отсчет начинается с нуля. Единица (+1) добавляется каждый раз, когда сегмент пересекает луч слева направо и вычитается единица (-1), когда сегмент пересекает луч справо налево . После подсчета пересечений, если результат равен нулю, то точка считается снаружи пути (сегмент не закрашивается). В противном случае она внутри.
Примечание. Правило действительно только для совокупности нескольких подпутей внутри одного параметра d=”…” команды path.

Из текста правила “nonzero” становится понятно, что результат заполнения цветом зависит от направления путей, образующие сегменты фигуры и количества их пересечений с лучом.
На Рис.1 два подпути образуют два сегмента, которые пересекают в одинаковом направлении луч, идущий из точки в бесконечность (зеленая линия). Алгебраическая сумма всех пересечений составляет +2, то есть результат не равен нулю, поэтому все сегменты фигуры будут закрашены.
Two paths in the same direction, fill rule nonzeroTwo paths in the opposite direction fill rule nonzero

На Рис.2 пути пересекают в разных направлениях луч, идущий из точки “B”. Их алгебраическая сумма, поэтому равна нулю. Как это не парадоксально, но эта точка считается по определению, снаружи фигуры, поэтому сегмент не закрашивается.

fill rule nonzero
На Рис.3 имеем три сегмента пересекающие луч в разных направлениях. Посчитаем для каждого сегмента алгебраическую сумму:
A=+1;
B= -1+1=0; – не закрашивается
C=+1-1+1=+1;

Из этих примеров можно вывести две закономерности:

Если используется правило заполнения fill-rule=”nonzero” то:
1. При одинаковом направлении двух и более подпутей параметра d=”…” все сегменты фигуры будут окрашены.
2. При разном направлении двух и более подпутей параметра d=”…” и при условии, что все соседние подпути имеют разные направления,- будут окрашены все нечетные сегменты. Соответственно чётные будут неокрашены.

Правило заполнения fill-rule=”evenodd”

Это более простое правило для понимания. Направление подпутей не учитывается. Точно так же, как и для правила “nonzero” проводится луч из точки внутри фигуры в бесконечность и производится подсчет порядковых номеров пересекаемых сегментов. Все нечетные сегменты будут окрашены.

Two paths in the same direction, fill rule evenoddTwo paths in the opposite direction fill rule evenodd

На Рис.4 подпути идут в одном направлении. На Рис.5 в разных напрвлениях.
Результат закрашивания будет одинаковым. Эти рисунки показывают, что результат закрашивания конкретного сегмента при команде fill-rule=”evenodd” не зависит от направления подпутей. Влияет только чётность или нечётность номера сегмента.
Примечание. Подсчёт номера сегмента идет снаружи по лучу внутрь фигуры.

На Рис.6 использованы 3 подпути, которые образуют 3 сегмента. Правило работает – (все нечетные сегменты) – 1 и 3 закрашены.
fill-rule="evenodd" Three-evenodd-z

На Рис.7 более сложный пример. Тут тоже используются три подпути, которые образуют квадрат, треугольник и трапецию с взаимно пересекаюшимися сторонами. В спецификации сказано, что луч можно провести под любым углом таким образом, чтобы он пересекал, границу сегмента, но не проходил по касательной к ней. На рисунке 7 изображены прерывистыми линиями два зелёных луча, идущих навстречу друг другу и один красный луч. Направления отсчёта сегментов указано стрелками. Видим, что правило выполняется по всем трем направлениям вдоль всех лучей: все сегменты с нечетными номерами – закрашиваются. Чётные – остаются незакрашенными.
⇚ SVG path часть 4

Добавить комментарий