Divide и разделение

В Paper.js методы divide и операции по разделению объектов позволяют создавать сложные композиции из базовых форм. Эти операции основываются на математическом вычислении пересечений, объединении или разнице между путями (Paths) и кривыми (CompoundPath), что дает возможность строить динамические векторные рисунки.


Метод Path.divide(path)

Метод divide используется для разделения одного пути (Path) другим. Его синтаксис:

var newPaths = path1.divide(path2);

Параметры:

  • path1 – исходный путь, который будет разделен.
  • path2 – путь, который пересекает path1.

Возвращаемое значение: массив новых путей, образовавшихся после разбиения.

Пример:

var path1 = new Path.Rectangle(new Point(50, 50), new Size(200, 100));
path1.fillColor = 'lightblue';

var path2 = new Path.Circle(new Point(150, 100), 60);
path2.fillColor = 'pink';

var result = path1.divide(path2);

В результате path1 будет разделен по границе path2, а метод вернет массив новых объектов Path, которые представляют собой разрезанные сегменты исходного прямоугольника.


Особенности использования divide

  1. Только пересекающиеся сегменты: разделение происходит только там, где пути пересекаются. Если пересечений нет, массив будет пустым.
  2. Сохраняется исходная геометрия: оригинальные объекты не изменяются, если не присвоить результат обратно.
  3. Сложные формы: divide может работать с произвольными кривыми и ломанными линиями, но порядок сегментов и направление пути может повлиять на результат.

Работа с CompoundPath

CompoundPath представляет собой комбинацию нескольких путей с возможностью создания вырезов и отверстий. Разделение CompoundPath работает аналогично, но нужно учитывать, что внутренние пути могут быть автоматически организованы в положительные и отрицательные области.

var compound = new CompoundPath({
    children: [
        new Path.Rectangle(new Point(50, 50), new Size(200, 100)),
        new Path.Circle(new Point(150, 100), 50)
    ],
    fillRule: 'evenodd'
});

var cutter = new Path.Circle(new Point(150, 100), 60);
var split = compound.divide(cutter);

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


Практика разбиения форм по точкам и сегментам

Помимо использования готового метода divide, Paper.js позволяет программно разрезать объекты на сегменты:

  • Разделение по точке: метод Path.split(index) разрезает путь на два в указанном индексе сегмента.
var path = new Path.Circle(new Point(150, 150), 100);
var firstSegment = path.split(10); // возвращает новый путь от сегмента 10
  • Объединение после разбиения: для сложных операций можно использовать комбинацию Path.subtract(), Path.intersect() и Path.unite(), чтобы имитировать динамическое разбиение сложных форм.

Визуальное разделение с анимацией

Разделение форм можно применять не только статически, но и динамически, создавая интерактивные эффекты:

var rect = new Path.Rectangle(new Point(50, 50), new Size(200, 100));
rect.fillColor = 'blue';

var circle = new Path.Circle(new Point(50, 50), 50);
circle.fillColor = 'red';

function onFrame(event) {
    circle.position.x += 2;
    if (circle.intersects(rect)) {
        var parts = rect.divide(circle);
        rect.remove();
        parts.forEach(function(p) {
            p.fillColor = 'blue';
        });
    }
}

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


Оптимизация разбиений

  • Минимизация сегментов: при больших формах метод divide может создавать много мелких Path, что увеличивает нагрузку на рендеринг. В таких случаях лучше использовать предварительное упрощение через path.simplify().
  • Контроль направления: порядок сегментов и направление пути (clockwise/anticlockwise) влияет на результат пересечения, особенно при работе с CompoundPath.
  • Комбинированные операции: часто divide применяют совместно с intersect и subtract, чтобы создавать сложные вырезы и декоративные фигуры.

Использование divide для интерактивных интерфейсов

Paper.js позволяет использовать divide в реальном времени, реагируя на действия пользователя:

  • Разделение объектов при перетаскивании мышью.
  • Динамическое обновление композиции при изменении формы «резака».
  • Анимационные эффекты разрезания объектов, создающие иллюзию резки или разрушения.

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

Хотите, чтобы я сразу сделал этот блок?