GetIntersections и получение точек пересечения

В библиотеке Paper.js метод getIntersections используется для вычисления точек пересечения между геометрическими объектами. Он является частью API класса Item и чаще всего применяется к объектам типа Path, CompoundPath и другим производным.

Метод возвращает массив объектов пересечений (CurveLocation), каждый из которых содержит подробную информацию о точке пересечения: координаты, параметры кривых и ссылки на участвующие сегменты.


Базовый синтаксис

var intersections = path1.getIntersections(path2);
  • path1 — первый объект (Path)
  • path2 — второй объект (Path)
  • intersections — массив найденных пересечений

Если второй аргумент не передан, метод ищет самопересечения:

var intersections = path.getIntersections();

Структура объекта пересечения

Каждый элемент массива — это объект CurveLocation, содержащий:

  • point — координаты точки пересечения (Point)
  • index — индекс сегмента в кривой
  • parameter — положение на кривой (от 0 до 1)
  • curve — ссылка на кривую (Curve)
  • path — путь, к которому принадлежит точка
  • intersection — связанный объект пересечения на другом пути

Пример доступа:

intersections.forEach(function(loc) {
    console.log(loc.point); // координаты точки
});

Пример: пересечение двух линий

var path1 = new Path.Line({
    from: [50, 50],
    to: [150, 150],
    strokeColor: 'black'
});

var path2 = new Path.Line({
    from: [50, 150],
    to: [150, 50],
    strokeColor: 'black'
});

var intersections = path1.getIntersections(path2);

intersections.forEach(function(loc) {
    new Path.Circle({
        center: loc.point,
        radius: 5,
        fillColor: 'red'
    });
});

Результат: одна точка пересечения, визуально отмеченная кругом.


Пересечение сложных кривых

Метод работает не только с прямыми линиями, но и с кривыми Безье:

var path1 = new Path.Circle({
    center: [100, 100],
    radius: 50,
    strokeColor: 'blue'
});

var path2 = new Path.Rectangle({
    point: [80, 80],
    size: [100, 60],
    strokeColor: 'green'
});

var intersections = path1.getIntersections(path2);

В этом случае может быть найдено несколько точек пересечения.


Самопересечения

Если вызвать getIntersections без аргументов, будут найдены точки, где путь пересекает сам себя:

var path = new Path({
    segments: [
        [50, 50],
        [150, 150],
        [50, 150],
        [150, 50]
    ],
    closed: true,
    strokeColor: 'black'
});

var intersections = path.getIntersections();

Такой подход полезен при анализе сложных форм или выявлении ошибок в геометрии.


Работа с параметрами кривой

Каждая точка пересечения содержит параметр parameter, определяющий положение на кривой:

  • 0 — начало сегмента
  • 1 — конец сегмента

Это позволяет выполнять точную интерполяцию:

var loc = intersections[0];
var curve = loc.curve;

var pointAt = curve.getPointAtTime(loc.parameter);

Оптимизация и производительность

Метод getIntersections может быть ресурсоёмким, особенно при работе с:

  • большим количеством сегментов
  • сложными кривыми
  • множественными объектами

Рекомендации:

  • минимизировать количество сегментов (simplify())
  • избегать лишних вычислений в анимациях
  • использовать bounding box (bounds) для предварительной фильтрации

Пример проверки перед вычислением:

if (path1.bounds.intersects(path2.bounds)) {
    var intersections = path1.getIntersections(path2);
}

Фильтрация результатов

Иногда требуется выбрать только определённые точки пересечения:

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

var filtered = intersections.filter(function(loc) {
    return loc.point.x > 100;
});

По сегменту:

var filtered = intersections.filter(function(loc) {
    return loc.index === 0;
});

Взаимные ссылки пересечений

Каждый объект CurveLocation содержит ссылку intersection, указывающую на соответствующую точку на другом пути:

var loc1 = intersections[0];
var loc2 = loc1.intersection;

console.log(loc1.point.equals(loc2.point)); // true

Это важно при симметричных вычислениях и анализе взаимодействия объектов.


Практическое применение

1. Детекция столкновений

if (path1.getIntersections(path2).length > 0) {
    console.log('Столкновение обнаружено');
}

2. Разделение путей Использование пересечений для разрезания кривых:

var loc = intersections[0];
var newPath = path1.splitAt(loc);

3. Построение сложных фигур Пересечения используются при булевых операциях (unite, intersect, subtract).


Особенности и ограничения

  • Пересечения вычисляются с учётом математической точности, возможны погрешности при очень близких кривых
  • Для замкнутых путей учитываются все сегменты
  • Пересечения на концах сегментов могут дублироваться

Отладка и визуализация

Для анализа удобно визуализировать точки пересечения:

intersections.forEach(function(loc) {
    var marker = new Path.Circle({
        center: loc.point,
        radius: 3,
        fillColor: 'red'
    });

    var text = new PointText({
        point: loc.point.add([5, -5]),
        content: loc.index,
        fillColor: 'black',
        fontSize: 10
    });
});

Взаимодействие с другими методами

getIntersections часто используется вместе с:

  • splitAt() — разделение пути
  • getLocationAt() — получение позиции на кривой
  • getNearestLocation() — поиск ближайшей точки
  • intersect() — булево пересечение

Сравнение с intersect()

Метод Назначение
getIntersections Получение точек пересечения
intersect Создание нового пути пересечения

Пример:

var shape = path1.intersect(path2);

Здесь возвращается новый Path, а не массив точек.


Работа с CompoundPath

Метод корректно обрабатывает сложные пути:

var compound = new CompoundPath({
    children: [path1, path2]
});

var intersections = compound.getIntersections(otherPath);

Пересечения вычисляются для всех вложенных путей.


Числовая стабильность

При работе с кривыми Безье важно учитывать:

  • накопление ошибок при множественных операциях
  • чувствительность к координатам с плавающей точкой

Для повышения стабильности:

paper.settings.insertItems = false;

Или использовать округление координат:

var rounded = loc.point.round();

Использование в анимации

При динамических сценах пересечения пересчитываются на каждом кадре:

function onFrame() {
    var intersections = path1.getIntersections(path2);
}

Важно контролировать нагрузку и оптимизировать количество объектов.


Обработка отсутствия пересечений

Метод всегда возвращает массив:

if (intersections.length === 0) {
    console.log('Нет пересечений');
}

Это позволяет избежать ошибок при доступе к элементам.


Вложенные пересечения

В сложных сценах возможны множественные пересечения:

  • пересечение нескольких сегментов
  • касательные (одна точка)
  • наложение (много точек)

Для устранения дубликатов:

var unique = [];
intersections.forEach(function(loc) {
    if (!unique.some(p => p.equals(loc.point))) {
        unique.push(loc.point);
    }
});

Геометрический смысл

Метод реализует поиск решений системы уравнений кривых:

  • для линий — аналитическое решение
  • для кривых Безье — численные методы

Это делает getIntersections универсальным инструментом для геометрических вычислений.


Итоговая роль в архитектуре Paper.js

getIntersections — ключевой механизм анализа взаимодействия объектов, лежащий в основе:

  • булевых операций
  • коллизий
  • геометрического моделирования
  • построения сложных векторных форм

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