Как определить пересечение CGPaths
"Мой вопрос" похож на этот.
У меня есть 2 CGPathRef и 1 будет перемещаться пальцем. Я хочу найти, пересекаются ли 2 CGPathRef? Этот вопрос задавали почти 2 года назад, и я хочу знать, было ли что-то найдено в среднем.
Ответы
Ответ 1
Это довольно старый, но я нашел, что он ищет аналогичное решение, в моей проблеме, которую я хотел найти, когда круг перекрывается с контуром (особый случай вашего вопроса).
Я решил это, используя CGPathCreateCopyByStrokingPath
, чтобы создать поглаженную версию исходного пути, используя радиус круга в качестве ширины штриха. Если центральная точка круга перекрывает положенный путь, исходный путь перекрывает круг.
BOOL CGPathIntersectsCircle(CGPathRef path, CGPoint center, CGFloat radius)
{
CGPathRef fuzzyPath;
fuzzyPath = CGPathCreateCopyByStrokingPath(path, NULL, radius,
kCGLineCapRound,
kCGLineJoinRound, 0.0);
if (CGPathContainsPoint(fuzzyPath, NULL, center, NO))
{
CGPathRelease(fuzzyPath);
return YES;
}
CGPathRelease(fuzzyPath);
return NO;
}
Изменить: небольшая ошибка, в которой fuzzyPath не был освобожден.
Ответ 2
Я написал интерфейс обнаружения столкновений на основе пикселов на основе CGPathRefs. Это требует, чтобы вы добавили несколько исходных каталогов в свой проект, и он работает только с ARC, но он должен хотя бы показать вам, как можно сделать что-то подобное. Он в основном рисует два пути в двух отдельных контекстах, а затем выполняет поэтапные проверки, чтобы увидеть, находятся ли какие-либо пиксели на обоих путях. Очевидно, что это будет медленно запускаться каждый раз, когда пользователь перетаскивает свой палец, но это, безусловно, может быть сделано каждые полсекунды или около того, возможно, даже не в основном потоке.
Это самый простой способ сделать что-то подобное, и легко может быть, что нет лучшего способа, кроме использования большого количества математики.
Ответ 3
В общем случае найти пересечение двух произвольных CGPaths будет очень сложным.
Есть способы сделать приближения. Проверка пересечений ограничивающих прямоугольников является хорошим первым шагом. Вы также можете разделить кривую и повторить процесс, чтобы получить лучшие приближения. Другой вариант - сгладить пути и посмотреть, пересекаются ли какие-либо из сегментов линии сплющенных путей.
Однако в общем случае все становится очень неприятным очень быстро. Рассмотрим, например, тот факт, что два кубических сегмента безье (не говоря уже о целом пути... только один сегмент) могут пересекаться с другим сегментом с точностью до 6 точек. Чем больше сегментов на вашем пути, тем больше потенциальных пересечений. Существует также проблема вырожденных кривых Безье, где сегмент имеет точку возврата, которая касается только одной точки другого сегмента. Это считается пересечением? (иногда да, иногда нет)
Это не ясно из вашего вопроса, но вы также можете рассмотреть пересечения штрихов, применяемых к кривым, и правильно учитывать объединения строк и митры. Это становится еще сложнее. Macromedia FreeHand (программа для рисования похожа на Adobe Illustrator) имела очень большую, сложную, сильно математическую библиотеку для обнаружения произвольных пересечений кривой безье. Проблема нелегко решить.
Ответ 4
Чтобы найти пересечение двух CAShapeLayers, мы можем использовать метод ниже, CAShapeLayer не будет возвращать фрейм. Но мы можем получить фрейм refPath с помощью CGPathGetBoundingBox. Но это даст рамку в прямоугольнике. Я понимаю, что вы можете понять.
if (CGRectIntersectsRect(CGPathGetBoundingBox(layer.path), CGPathGetBoundingBox(layer.path)))