Как я могу получить все точки в кривой CGPath или в квадрате - PullRequest
18 голосов
/ 08 мая 2009

Я сделал четырехугольный путь, используя метод CGPathAddQuadCurveToPoint. Я прекрасно понял путь. Но я хочу знать все координаты, которые участвуют в пути.

Есть ли способ получить все точки координат на пути?

Если нет, то у вас нет другого решения для математического извлечения всех точек кривой.

Спасибо заранее, Вамши

Ответы [ 6 ]

14 голосов
/ 27 июля 2012

Вы можете сделать это, используя библиотечную процедуру wykobi C ++ для кубических кривых Безье. Библиотека Уикоби также поддерживает квадратичные кривые Безье.

Конечно, как кто-то указал, вы не хотите, чтобы все очки (хотя и не невозможные, это заняло бы бесконечное время :). Wykobi позволяет легко получить определенное количество точек - если ваши начальные, c1, c2 и конечные точки (где c1, c2 - контрольные точки) в точности совпадают с теми, которые даны CGContextAddCurveToPoint, то точки будут лежать идеально на линии, нарисованной основной графикой - так вы можете сделать такие вещи, как нарисовать узор в нескольких точках пути.

См .: http://www.codeproject.com/Articles/22568/Computational-Geometry-C-and-Wykobi

Кроме того, после того, как я начал использовать wykobi, я услышал, что есть похожая, может быть, даже лучшая библиотека, которая является частью Boost, но еще не проверил ее.

Я создал C ++ Class WPoint как мост между точками wykobi и CGPoints (удовольствие C ++!). Вот некоторый код (без WPoint, но вы можете представить, что он точно такой же, как CGPoint, поэтому, если вы сделаете правильный бросок, вы сможете легко конвертировать.

        NSMutableArray* result = [[NSMutableArray alloc] init];
        wykobi::cubic_bezier<CGFloat,2> bezier;
        bezier[0] = (WPoint)p1;  // start point, in CG we did a CGMoveToPoint
        bezier[1] = (WPoint)b1i; // control 1
        bezier[2] = (WPoint)b2i; // control 2
        bezier[3] = (WPoint)p2;  // end point

        std::vector<WPoint> point_list;
        int numPoints = p2.dist(p3) * pointDensity;
        // *** here's the magic ***
        wykobi::generate_bezier(bezier,std::back_inserter(point_list), numPoints);

        for (int i=0; i<numPoints; i++) {
            CGPoint p = (CGPoint)(point_list[i]);
            [result addObject:[NSValue valueWithCGPoint:p]];
        }

// result has your points!

Вот ссылка на библиотеку геометрии Boost: http://www.boost.org/doc/libs/1_47_0/libs/geometry/doc/html/geometry/introduction.html

2 голосов
/ 18 декабря 2013

Использовать CGContextSetLineDash

Цель этой функции - создать пунктирную линию, но вы можете использовать ее для получения меньших сегментов. Начальная точка каждого сегмента может рассматриваться как точка.

CGSize bbSize = CGPathGetBoundingBox(path).size;
UIGraphicsBeginImageContext(bbSize);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, 1.0);
CGContextAddPath(ctx, path);
CGContextSetLineDash(ctx, phase, lengths, count);
CGContextReplacePathWithStrokedPath(ctx);
result = CGContextCopyPath(ctx);
UIGraphicsEndImageContext();
1 голос
/ 08 мая 2009

Если вы хотите работать с элементами moveto, lineto и curveto пути, используйте CGPathApply . Вы передаете этот указатель на функцию в вашей программе, и она вызывает эту функцию один раз для каждого элемента пути.

К сожалению, нет способа просто запросить каждый элемент, как в AppKit NSBezierPath . Функция является единственным способом.

Если вы хотите определить каждый пиксель, пересекаемый траекторией, слишком плохо - это не практично, и я даже не могу понять, зачем вам эта информация. Некоторые контексты, такие как контексты PDF , даже не имеют пикселей; в этих случаях любой вопрос, касающийся пикселей, не является следствием.

0 голосов
/ 12 июня 2009

Полагаю, вы ищете что-то эквивалентное классу Java2D FlateningPathIterator. Например, path.getPathIterator(null, 1.0) в Java2D возвращает итератор только из сегментов 'lineTo', даже если исходный путь имел такие кривые, как quTTo и quadTo, двойной аргумент управляет 'плоскостью', предоставляя вам простой способ вычисления любой точки кривой. Я ищу то же самое в Какао, но ничего не нашел. Если вы найдете решение, пожалуйста, дайте мне знать. Вокруг имеются кривые (например, http://sourceforge.net/projects/curves/)), которые могут быть перенесены, но всегда есть риск, что если вы не используете тот же алгоритм, что и у Cocoa, то могут возникнуть ошибки между вашей интерполяцией и штрихованным NSBezierPath / CGPath.

0 голосов
/ 08 мая 2009

Если нет, у вас нет другого решения для математического извлечения всех точек кривой.

Для чего они вам нужны, т.е. какую проблему вы пытаетесь решить? Если это пересекает две кривые, вы можете сделать это математически. Просто установите два уравнения кривой равными друг другу и решите для неизвестного.

0 голосов
/ 08 мая 2009

Квадратичная кривая - это просто кривая. Невозможно получить список всех точек на нем, потому что точек бесконечно много, и это не простой отрезок.

См. Получение информации о кварцевых путях для списка функций, которые вы можете использовать для запроса объекта CGPath. К сожалению, похоже, что наиболее полезная информация, которую вы собираетесь получить, - это CGPathContainsPoint(), которая сообщает вам, содержится ли заданная точка в области пути.

...